在异步返回类型上

想知道为什么我们应该指定async方法确实返回Task对象。

使用async关键字指定它似乎是多余的,因为你没有真正创建Task对象,所以它很混乱。

据我所知,编译器会为Task对象创建发出必要的代码(无论是在等待调用还是用新任务包装返回)。

我真的不喜欢声明类型和返回类型之间的不一致。

我有一篇博文 ,详细描述了推理。 考虑推断返回类型,但他们决定不这样做。

使用显式返回类型, async关键字更多是实现细节。 拥有显式返回类型有两个原因:

  • 方法签名是一致的(在声明时与使用IntelliSense或reflection观察时相同)。
  • async voidasync Task之间存在差异。 使用推断的返回类型,没有明确的方法来定义async void方法。

这不是一个真正的问题:它更像是一个咆哮,因此不是特别适合StackOverflow:

我真的不喜欢声明类型和返回类型之间的不一致。

如果你想抱怨,开始写博客并抱怨。 让我们重新提出这个问题

async方法返回的声明类型可能是,例如Task但该方法中的return语句返回的表达式必须可以隐式转换为int ,而不是Task 。 这可能令人困惑。 什么样的设计原则certificate了这种行为?

你是对的,这可能令人困惑。 这是令人困惑的,因为async方法将我们非常习惯的两件事分开作为一件事。 这两件事是:

  • 当控制在此方法的调用者中恢复时,返回什么类型的对象?
  • 从该方法向其继续传递什么类型的对象? 请记住,方法的延续方法完成时运行的代码

在同步方法中,这两件事总是相同的,因为调用者中的恢复点同步方法的延续 。 但是异步方法的重点是调用者中的代码不是方法的延续。 通过设置与其关联的任务的继续来控制方法的继续。

这就是声明的返回类型和return语句的类型不同的原因。 调用者想要一个Task但该方法的延续需要一个intreturn语句表示“此方法已完成;无论方法是同步还是异步,都将此值赋予我的continuation”。

听起来你问为什么public async int MyMethodAsync()不会自动编译为实际返回Task

答案是最少惊喜的原则:方法签名中声明的返回类型始终是实际的返回类型。
这样,当您读取方法声明时,您始终可以知道调用方法时看到的实际返回类型,而无需查看修饰符并记住特殊规则。