Задача и задача < T > Сменная?

cwharris спросил: 12 мая 2018 в 05:09 в: c#

Я столкнулся с типизированной ситуацией при попытке вызвать конкретный метод перегрузки, и теперь мне любопытно: почему следующее не вызывает ошибку компиляции?

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.

I ожидал бы, что все эти примеры потерпят неудачу.

Ошибка из третьей строки (c): Cannot cast expression of type 'System.Threading.Tasks.Task<System.Threading.Tasks.Task>' to type 'Task<Task<Task>>'

3 ответа

Есть решение
Michael Gunter ответил: 12 мая 2018 в 05:25

Task<T> происходит от Task.

Ваша первая строка похожа на (int) (object) 1, что совершенно законно, потому что все ( в том числе int) происходит из Object.

Вторая строка - это то же самое с контравариантностью в действии.

Третья строка терпит неудачу, потому что параметр T Task<T> не настроен для ковариации (и, действительно, это не может быть потому, что Task<T> - это класс, а не интерфейс или делегат). Он работает для Func<TResult>, потому что Func<TResult> настроен для ковариации (т. Е. Объявлен как Func<out TResult>)). Задачи, возможно, были разработаны, чтобы запретить это по целям или они забыли сделать это.

spender ответил: 12 мая 2018 в 05:20
Пункт 3 не работает, потому что Task<T> не выводится из ковариантного интерфейса / делегата. Func<out TResult>.
Michael Gunter ответил: 12 мая 2018 в 05:21
@spender Путь впереди вас. :)
cwharris ответил: 12 мая 2018 в 05:22
@spender Task является классом и поэтому не может иметь аргументы типа co / contra-varience. Это простая проблема иерархии заданий.
cwharris ответил: 12 мая 2018 в 05:26
@spender Эрик Липерт, похоже, не знает, поэтому я не собираюсь это делать. :)
Dmitry Pavliv ответил: 12 мая 2018 в 05:15
Поскольку Task ^ 3 не наследуется от Task ^ 2
cwharris ответил: 12 мая 2018 в 05:48

Это экстраполяция ответа Майкла :

Для a: Task<T> происходит от Task, так что это нормально.

Для b: Func является делегат с ковариацией и поэтому неявно преобразует Task

Для c: Task нельзя использовать аргументы типа ковариации, так как это класс, и Task<Task<T>> не получается из Task<T>, поэтому это НЕ ОК.