Why is Task not co-variant?

前端 未结 2 978
逝去的感伤
逝去的感伤 2020-11-28 11:50
class ResultBase {}
class Result : ResultBase {}

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

The compiler tel

相关标签:
2条回答
  • 2020-11-28 12:05

    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 classes 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.

    0 讨论(0)
  • 2020-11-28 12:28

    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>();
    }
    
    0 讨论(0)
提交回复
热议问题