cho*_*d37 50 c# task covariance
class ResultBase {}
class Result : ResultBase {}
Task<ResultBase> GetResult() {
return Task.FromResult(new Result());
}
Run Code Online (Sandbox Code Playgroud)
编译器告诉我它不能隐式转换Task<Result>为Task<ResultBase>.有人可以解释为什么会这样吗?我希望协方差可以让我以这种方式编写代码.
tac*_*cos 21
根据可能知道的人 ...
理由是混淆的缺点超过了协方差的优势(即每个人都必须决定是否在代码中的每个地方使用Task或ITask).
听起来对我来说,无论哪种方式都没有非常引人注目的动机. ITask<out T>会需要很多新的重载,可能还有很多新的重载(我无法证明实际的基类是如何实现的,或者它与一个简单的实现相比有多特别)但更多的是以类似这样linq的扩展方法的形式.
其他人提出了一个很好的观点 - 时间会更好地用于class协变和逆变.我不知道会有多难,但这对我来说听起来更好用.
另一方面,有人提到yield return在async方法中提供真实的功能会非常酷.我的意思是,没有狡猾的手.
我意识到我迟到了,但这是我用来解释这个缺失功能的扩展方法:
/// <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;
}
Run Code Online (Sandbox Code Playgroud)
这样你就可以这样做:
class ResultBase {}
class Result : ResultBase {}
Task<Result> GetResultAsync() => ...; // Some async code that returns Result
Task<ResultBase> GetResultBaseAsync()
{
return GetResultAsync().AsTask<Result, ResultBase>();
}
Run Code Online (Sandbox Code Playgroud)