为何在Task组合器中用Task.FromResult<T>而非直接返回Result?
Otherwise Task组合器中
await Task.FromResult<T>(innerTask.Result)的写法分析 首先给出《Concurrency in .NET》第10.2节的Otherwise Task组合器实现代码:
public static Task<T> Otherwise<T>(this Task<T> task, Func<Task<T>> orTask) => task.ContinueWith(async innerTask => { if (innerTask.Status == TaskStatus.Faulted) return await orTask(); return await Task.FromResult<T>(innerTask.Result); }).Unwrap();
注:印刷版书籍中
Otherwise方法被错误标记为async,导致代码无法编译;但GitHub上的官方代码已修正了这个问题。
针对代码中return await Task.FromResult<T>(innerTask.Result)的写法,我们可以从以下几点分析:
- 由于
ContinueWith的回调是在innerTask完成后才会执行,此时innerTask.Result已经处于可用状态,不需要额外的异步等待。 - 直接返回
innerTask.Result和通过Task.FromResult包装后再await的效果完全一致:两者都会将结果同步返回给上层Unwrap()后的任务。 - 经测试验证,当
innerTask被取消时,两种写法的异常处理逻辑没有差异——都会正确抛出取消异常。
结论:使用await Task.FromResult<T>(innerTask.Result)没有任何实际益处,反而会模糊代码意图,增加不必要的异步包装开销。更优的写法是直接返回innerTask.Result,代码更简洁清晰:
public static Task<T> Otherwise<T>(this Task<T> task, Func<Task<T>> orTask) => task.ContinueWith(async innerTask => { if (innerTask.Status == TaskStatus.Faulted) return await orTask(); return innerTask.Result; }).Unwrap();
内容的提问来源于stack exchange,提问作者RMills330
相关产品推荐
相关产品推荐

