将具体的Task <TImplementation>分配给Task <TInterface>类型的变量

Dan*_*ark 4 c# inheritance casting interface task-parallel-library

考虑一个Foo完全实现的类IFoo.同时,考虑一项任务Task<IFoo>.

为什么在调用以下内容时会抛出编译错误;

Task<IFoo> task = Task.Factory.StartNew(() => new Foo());
Run Code Online (Sandbox Code Playgroud)

编译器声明它无法从源类型转换Task<Foo>Task<IFoo>.虽然这是有道理的,因为它们本质上是两种不同的类型,它不会与IList<IFoo> list = new List<IFoo>{new Foo(/* construct */)};其他类似的任务处于相同的前提下吗?

目前我正在强迫演员进入界面,但这感觉不必要.

Ale*_*lex 9

那是因为这个语句Task.Factory.StartNew(() => new Foo());返回一个类型的实例Task<Foo>.

并且鉴于Task<>该类是具体类,它不能是协变的,除非它实现了协变接口(即ITask<out T>).

请注意,有一个uservoice主题可以做到:"使任务实现协变接口ITask".

还要注意以下可能的解释,为什么它现在的方式,"任务类缺乏协方差":

框架指南是:

  • 如果你的框架由于其他原因已经包含了一个接口,那么无论如何都要使它成为co + contravariant.
  • 但是,不要仅为了实现协同+逆转而引入接口.

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

现在你必须这样做:

Task<IFoo> task = Task.Factory.StartNew<IFoo>(() => new Foo());
Run Code Online (Sandbox Code Playgroud)