Task<IDictionary<double, double>> GetTaskDict() { return Task.FromResult(new Dictionary<double, double> () ); }Este código no se compila porque no podemos convertir Task<Dictionary<double, double>> a Task<IDictionary<double, double>>. ¿Por qué esto no funciona? ¿Es posible hacer que este tipo de llamada funcione? Esto se opone a un método como este que compila
IDictionary<double, double> GetTaskDict() { return new Dictionary<double, double> (); }return Task.FromResult<IDictionary<double, double>>(new Dictionary<double, double>()); Esto se debe a que Task<T> no es covariante, por lo que Task<Foo> no es intercambiable con Task<IFoo> incluso si Foo : IFoo .
También puede considerar usar ValueTask<T> si va a tener muchos resultados disponibles de forma sincrónica; es significativamente más económico en ese escenario. Incluso puede usar el uso implícito de new() en ese escenario:
ValueTask<IDictionary<double, double>> GetTaskDict() { return new(new Dictionary<double, double>()); } (aquí, new(...) se interpreta como new ValueTask<IDictionary<double, double>>(...) del tipo de retorno declarado del método)
Supongamos que fuera posible.
Entonces alguien podría hacer esto:
Task<IDictionary<double, double>> myTaskDict = new Task<Dictionary<double, double>>(); Task.SetResult(myIDictionaryWhichIsNotActuallyADictionary); En otras palabras, como ha dicho @MarcGravell, Task no es covariante, y por muy buenas razones.
Sin embargo, puede especificar el tipo explícitamente así:
Task<IDictionary<double, double>> GetTaskDict() { return Task.FromResult<IDictionary<double, double>>(new Dictionary<double, double>()); }