非异步执行路径 return 同步结果能否在 "async" 方法中

Can non-asynchronous execution paths return synchronous results in an "async" method

考虑以下方法:

public async Task<string> GetNameOrDefaultAsync(string name)
{
    if (name.IsNullOrDefault())
    {
        return await GetDefaultAsync();
    }

    return name;
}

当提供name时,方法执行时不会发生等待,但该方法将正确编译。

但是,此方法会产生如下所示的构建警告:

public async Task<string> GetDefaultAsync()
{
    return "foobar";
}

[CS1998] This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.

为什么 GetNameOrDefaultAsync 可以 return 无需等待,并且不会导致编译器警告,但 GetDefaultAsync 必须等待才能编译?

执行以下操作会有所改进吗?:

public async Task<string> GetNameOrDefaultAsync(string name)
{
    if (name.IsNullOrDefault())
    {
        return await GetDefaultAsync();
    }

    return await Task.FromResult(name);
}

这里我们将没有不await东西的执行路径。

Why is it that GetNameOrDefault can return without ever awaiting, and not result in a compiler warning

因为有些执行路径确实使用了 await,并且要能够使用 await,方法需要是 async.

另一方面,如果 没有 路径使用 awaitasync 关键字显然是多余的,因此会出现警告。

Would it be an improvement to do the following? return await Task.FromResult(name);

不,Task.FromResult 只是将 name 包装在一个 Task 对象中,该对象处于完成状态,这意味着 await 会立即再次展开它。

这分配了一个不必要的 Task,并没有实现。


顺便说一句,如果 name.IsNullOrDefault() 几乎总是 false,即使用 await 是例外而不是规则,您可以通过使用 ValueTask 来减少分配: