为什么 C# 中的异步调用需要这样声明,如果它们所在的方法已经用 'async' 关键字声明?

Why do asynchronous calls in C# need to be declared as such if the method they reside in is declared with the 'async' keyword already?

现在,我发现的这个 "nitpick" 有 99% 的可能性完全是由于我自己的无知 - 我是一名初级 Web 开发人员,只是偶尔接触 C# 几个月,所以我提前为我的问题可能的愚蠢道歉。我的大部分经验是使用 PHP 和 JS。

如果我有一个使用 async 关键字声明的方法:

    public async Task<ActionResult> Create(MyObject myObject)
    {
    }

为什么我还必须像这样明确指定 LINQ 语句是异步的:

    public async Task<ActionResult> Create(MyObject myObject)
    {
        if (ModelState.IsValid)
        {
            myObject.Id = Guid.NewGuid();
            myObject.DisplayId = await db.MyObjects.MaxAsync(m => m.DisplayId) + 1;
            db.MyObjects.Add(myObject);
            await db.SaveChangesAsync();
            return RedirectToAction("Index");
        }
        return View(myObject);
    }

难道 C# 编译器不能足够聪明地弄清楚因为该方法是异步的,所以我想在该方法中执行的 LINQ 语句也应该是异步的吗?

我想我真正的不满是现在大多数 LINQ 方法都有一个异步孪生(SaveChangesAsyncMaxAsyncFirstOrDefaultAsync),我必须使用 await 关键字每次我想执行这样的调用。这似乎过于冗长和不必要。

如果仍然需要对调用的同步性进行精细控制,为什么 C# 开发人员不简单地允许我使用 .Await().Async()Sync() 方法可以追加吗?

Can't the C# compiler be clever enough to figure out that because the method is asynychronous, the LINQ statements I want to execute within the method should be asynchronous too?

如果想在异步方法中进行同步调用怎么办?

您希望同一方法是同步的还是异步的,这取决于您是否处于异步方法中?我想一种语言可以做到这一点,但它需要一个根本不同的模型,而不是 C# 使用的模型。另外,我不确定这是个好主意;这可能很混乱。最好让事情明确 IMO。

I guess my real beef with this is that there's now an asynchronous twin for most LINQ methods (SaveChangesAsync, MaxAsync, FirstOrDefaultAsync), and I have to use the await keyword every time I want to execute such calls. It seems excessively verbose and unnecessary.

使用或不使用await没有相同的含义。如果你不使用 await,你只是检索任务,这在某些情况下很有用(例如,如果你想并行化任务。例如,考虑以下内容:

Task t1 = SomeAsyncOperation();
Task t2 = SomeOtherAsyncOperation();
await Task.WhenAll(t1, t2);

在上面的代码中,运行 操作是并行的。现在,如果您在每次调用时都使用 await:

await SomeAsyncOperation();
await SomeOtherAsyncOperation();

操作现在是顺序的。

开发人员需要控制这种事情。这就是 await 不能隐式的​​原因,因为它改变了代码的行为。

If granular control over the synchronicity of the call was still needed, why didn't the C# developers simply allow for an .Await() or .Async() method that I could append?

.Await() 方法如何比关键字更好?无论如何,这是行不通的。使用 await 关键字将方法体转换为状态机;方法调用无法做到这一点。

await 完全改变了方法代码的生成方式——状态机与线性代码——所以你不能用任何自定义的 .Await() 方法神奇地实现它,因为方法调用编译成线性码。

C# 通常选择显式方法而不是神奇地猜测意图 - 所以虽然在某些情况下编译器可能会猜测需要 await 调用但它不会。

请注意,var 通常也无法做出猜测:

var displayId = db.MyObjects.MaxAsync(m => m.DisplayId);

displayId 可能是 Task 或者如果编译器允许猜测丢失的 await 它可能是 int