为何未显式声明async、await的异步函数简写写法仍可正常运行?
核心原因
async本质只是编译器的语法糖标记,不决定方法是否是异步方法,也不要求方法必须返回Task,它的唯一作用是告诉编译器:要把当前方法的内部逻辑编译成异步状态机,用来处理方法内部的await关键字的等待逻辑。
第二种写法可以正常运行,本质是做了「Task透传」:
- 你调用的
TEntityRepository.GetAllAsync()本身就已经返回了一个Task<List<TEntity>>类型的异步任务对象,当前的GetEntitiesAsync方法没有任何需要在拿到这个Task之后再处理的逻辑,直接把这个Task对象原样返回给上层调用方即可。 - 因为方法内部没有用到
await关键字,自然不需要加async标记,编译器也不会生成多余的状态机,性能反而比第一种写法略好,这也是C#中推荐的简化写法。
注意事项
这种省略async/await的写法只适用「纯透传Task」的场景,如果有以下情况必须保留async/await:
- 方法内部需要在异步任务执行完成后做额外的逻辑处理(比如加工返回结果、打印日志等)
- 方法内部需要捕获异步任务执行过程中抛出的异常:如果没有await,异步任务的异常会被封装到返回的Task中,当前方法的try/catch只能捕获到调用
GetAllAsync时同步抛出的异常(比如参数校验失败),抓不到异步执行阶段的异常。 - 方法内部需要使用
using/using var管理资源生命周期,资源需要等异步任务执行完再释放的场景,如果直接透传Task,资源会在方法返回时就被释放,导致异步任务执行时资源已被销毁。
内容的提问来源于stack exchange,提问作者CorrieJanse
相关产品推荐
相关产品推荐

