class ResultBase {}
class Result : ResultBase {}
Task GetResult() {
return Task.FromResult(new Result());
}
The compiler tel
According to someone who may be in the know...
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 or ITask in every single place in their code).
It sounds to me like there is not a very compelling motivation either way. ITask<out T>
would require a lot of new overloads, probably quite a bit under the hood (I cannot attest to how the actual base class is implemented or how special it is compared to a naive implementation) but way more in the form of these linq
-like extension methods.
Somebody else made a good point - the time would be better spent making class
es covariant and contravariant. I don't know how hard that would be, but that sounds like a better use of time to me.
On the other hand, somebody mentioned that it would be very cool to have a real yield return
like feature available in an async
method. I mean, without sleight of hand.
I realize I'm late to the party, but here's an extension method I've been using to account for this missing feature:
/// <summary>
/// Casts the result type of the input task as if it were covariant
/// </summary>
/// <typeparam name="T">The original result type of the task</typeparam>
/// <typeparam name="TResult">The covariant type to return</typeparam>
/// <param name="task">The target task to cast</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static async Task<TResult> AsTask<T, TResult>(this Task<T> task)
where T : TResult
where TResult : class
{
return await task;
}
This way you can just do:
class ResultBase {}
class Result : ResultBase {}
Task<Result> GetResultAsync() => ...; // Some async code that returns Result
Task<ResultBase> GetResultBaseAsync()
{
return GetResultAsync().AsTask<Result, ResultBase>();
}