Task 和 Task<T> 可以互换吗?

Are Task and Task<T> Interchangeable?

我 运行 在尝试调用特定方法重载时遇到了输入情况,现在我很好奇:为什么以下不会引发编译错误?

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>>'

Task<T> derives from Task.

你的第一行有点像 (int) (object) 1,这是完全合法的,因为一切(包括 int)都来自 Object.

你的第二行是同样的事情,但是逆变在起作用。

第三行失败,因为Task<T>T参数没有设置协方差(事实上,不可能是因为Task<T>是一个class,不是接口或委托)。它适用于 Func<TResult>,因为 Func<TResult> 设置的协方差(即声明为 Func<out TResult>)。任务可能被设计为故意禁止这样做,或者他们忘记这样做。

这是 的外推:

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

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

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