如何从非异步Task正确返回TypedResults?
核心原因
TypedResults.Ok()返回的是Ok类型实例,TypedResults.NotFound()返回的是NotFound类型实例,而Results<Ok, NotFound>是C#的鉴别联合类型。
直接调用Task.FromResult(TypedResults.Ok())时,编译器会自动推断Task.FromResult的类型参数为Ok,最终返回Task<Ok>;同理另一条分支返回Task<NotFound>,这两个类型都无法隐式转换为方法要求的Task<Results<Ok, NotFound>>,因此触发编译错误。
而在async方法中,编译器会自动完成隐式转换:当你return TypedResults.Ok()时,编译器会把Ok实例转换为Results<Ok, NotFound>类型,再包装成Task<Results<Ok, NotFound>>返回,这就是异步版本能正常编译的原因。
优雅的解决方法
不需要引入无意义的await,只需要给Task.FromResult指定显式的目标类型参数即可:
public Task<Results<Ok, NotFound>> ReceiveCommand(ICommand command) { // ... 业务逻辑 if (condition) return Task.FromResult<Results<Ok, NotFound>>(TypedResults.NotFound()); return Task.FromResult<Results<Ok, NotFound>>(TypedResults.Ok()); }
这样编译器会明确将NotFound/Ok实例转换为Results<Ok, NotFound>类型,再包装成对应Task,完美匹配方法返回类型,代码简洁且无多余异步开销。
补充说明
你提到的await Task.CompletedTask或await Task.FromResult()写法,本质是利用async方法的编译器转换逻辑间接完成类型转换,但会引入不必要的状态机生成(即便JIT会优化,代码也不够直观),显式指定Task.FromResult的类型参数是更直接、优雅的方案。
内容的提问来源于stack exchange,提问作者ZorgoZ

