Consider a class Foo
which wholly implements IFoo
.
Concurrently, consider a task Task<IFoo>
.
Why is it that when the following is called, a compilation error is thrown;
Task<IFoo> task = Task.Factory.StartNew(() => new Foo());
The compiler states that it cannot convert from source type Task<Foo>
to Task<IFoo>
. While this makes sense because they are essentially two differing types, would it not fall under the same premise as IList<IFoo> list = new List<IFoo>{new Foo(/* construct */)};
, or other similar assignments?
At the moment I am forcing a cast to the interface, but this feels unneccesary.
That is because this statement Task.Factory.StartNew(() => new Foo());
returns an instance of type Task<Foo>
.
And given that the Task<>
class is a concrete class, it cannot be covariant, unless it were implementing a covariant interface (i.e. ITask<out T>
).
Note that there is a uservoice topic to do just that: "Make Task implement covariant interface ITask".
Also note the following possible explanation on why it is the way is it now, "Lack of Covariance in the Task Class":
Framework guidelines are:
- If your framework already includes an interface for other reasons, then by all means make it co+contravariant.
- But don't introduce an interface solely for the purposes of enabling co+contravariance.
The justification is that the advantage of covariance is outweighed by the disadvantage of clutter (i.e. everyone would have to make a decision about whether to use
Task<T>
orITask<T>
in every single place in their code).
For now you will have to do:
Task<IFoo> task = Task.Factory.StartNew<IFoo>(() => new Foo());
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With