2015-05-25 148 views
4

考虑一个类Foo,它完全实现了IFoo。 同时,考虑任务Task<IFoo>将具体任务<TImplementation>分配给类型变量任务<TInterface>

为什么当调用以下内容时会引发编译错误;

Task<IFoo> task = Task.Factory.StartNew(() => new Foo()); 

编译器说,它不能从源类型Task<Foo>转换为Task<IFoo>。虽然这是有道理的,因为它们本质上是两种不同的类型,是否不会与IList<IFoo> list = new List<IFoo>{new Foo(/* construct */)};或其他类似的分配属于同一前提?

此刻我强制演员进入界面,但这种感觉并不合适。

+3

你的反例是不计。列表也不能被分配给IList 。 –

+0

嗯,你说得对。那么我想这件事就在同一条毯子下。 –

+0

我通常从波特兰水泥和水的混合物中回收混凝土。也许你可以编辑你的标题更具描述性。 –

回答

9

这是因为这种说法Task.Factory.StartNew(() => new Foo());返回Task<Foo>类型的实例。

并且考虑到Task<>类是一个具体类,除非它实现协变接口(即ITask<out T>),否则它不能是协变的。

请注意,有一个uservoice话题可以做到这一点:"Make Task implement covariant interface ITask"

还要注意为什么事情是这样的,现在以下可能的解释,"Lack of Covariance in the Task Class"

框架指导方针是:

  • 如果你的框架已经包含了其他原因的接口,然后通过一切手段使它合作+逆变。
  • 但是不要仅仅为了实现co +逆变的目的而引入接口。

的理由是,协方差的好处是杂乱的缺点抵销(即每个人都必须做出关于是否在他们的代码中使用Task<T>ITask<T>在每一个所决定)。

现在你要做的:

Task<IFoo> task = Task.Factory.StartNew<IFoo>(() => new Foo()); 
+0

谢谢,为此。我真的是为什么而不是如何,而这又碰撞了脑袋。 –

+0

@DanielPark如果您认为这个问题能够充分解决您的问题,您可能希望接受它作为答案,以便您的问题可以从“未回答的问题”列表中删除。 – Alex

0

您可以使用通用版本

Task<IFoo> task = Task.Run<IFoo>(() => new Foo());