Perché l’attività non è co-variante?

class ResultBase {} class Result : ResultBase {} Task GetResult() { return Task.FromResult(new Result()); } 

Il compilatore mi dice che non può convertire implicitamente Task in Task . Qualcuno può spiegare perché questo è? Mi sarei aspettato una co-varianza per permettermi di scrivere il codice in questo modo.

Secondo qualcuno che potrebbe essere al corrente …

La giustificazione è che il vantaggio della covarianza è superato dallo svantaggio della confusione (ovvero ognuno dovrebbe decidere se utilizzare Task o ITask in ogni singolo punto del proprio codice).

A me sembra che non ci sia una motivazione molto convincente in entrambi i casi. ITask richiederebbe un sacco di nuovi sovraccarichi, probabilmente un bel po ‘sotto il cofano (non posso attestare come viene implementata la class base effettiva o quanto sia speciale rispetto a un’implementazione ingenua) ma molto più sotto forma di questi metodi di estensione di linq .

Qualcun altro ha fatto un buon punto: il tempo sarebbe stato meglio speso rendendo le class covarianti e controvarianti. Non so quanto sarebbe difficile, ma mi sembra un uso migliore del tempo.

D’altra parte, qualcuno ha detto che sarebbe stato molto interessante avere un yield return reale come la funzione disponibile in un metodo async . Voglio dire, senza giochi di prestigio.

Mi rendo conto che sono in ritardo per la festa, ma ecco un metodo di estensione che ho utilizzato per tenere conto di questa caratteristica mancante:

 ///  /// Casts the result type of the input task as if it were covariant ///  /// The original result type of the task /// The covariant type to return /// The target task to cast [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Task AsTask(this Task task) where T : TResult where TResult : class { return task.ContinueWith(t => t.Result as TResult); } 

In questo modo puoi semplicemente fare:

 class ResultBase {} class Result : ResultBase {} Task GetResult() { return Task.FromResult(new Result()).AsTask(); }