任务和任务<t>是否可互换?

时间:2018-06-05 18:49:13

标签: c# task-parallel-library

我在尝试调用特定方法重载时遇到了打字情况,现在我很好奇:为什么以下不会导致编译错误?

var a = (Task<Task>) (Task) null; // fine.
var b = (Func<Task<Task>>) (Func<Task>) null; // fine.
var c = (Task<Task<Task>>) (Task<Task>) null; // compilation error.

我希望所有这些例子都失败。

第三行(c)出错: Cannot cast expression of type 'System.Threading.Tasks.Task<System.Threading.Tasks.Task>' to type 'Task<Task<Task>>'

2 个答案:

答案 0 :(得分:4)

Task<T>来自Task

您的第一行有点像(int) (object) 1,这完全合法,因为所有内容(包括int)都来自Object

你的第二行与行动中的逆变是一回事。

第三行失败,因为T的{​​{1}}参数未设置为协方差(事实上,它不能是因为Task<T>是一个类,而不是接口或委托) 。它适用于Task<T>,因为Func<TResult> 为协方差设置(即,它被声明为Func<TResult>)。任务可能被设计为不允许这样做,或者他们忘了这样做。

答案 1 :(得分:0)

这是Michael's answer的推断:

对于aTask<T>派生自Task,所以这没关系。

对于bFunc是具有协方差的委托,因此代表我们隐式地将Task转换为Task<T>Func没有改变,因此没问题。

对于cTask不能使用协变类型参数,因为它是一个类,Task<Task<T>>不是从Task<T>派生的,因此这不行。