C# 为什么返回等待任务。FromResult(true);而不是仅仅返回true?

C# 为什么返回等待任务。FromResult(true);而不是仅仅返回true?,c#,async-await,C#,Async Await,当您使用VS2017创建Xamarin Forms Master Detail示例时,您将获得一个使用以下方法生成的MockDataStore类 public async Task<bool> DeleteItemAsync(string id) { var _item = items.Where((Item arg) => arg.Id == id).FirstOrDefault(); items.Remove(_item);

当您使用VS2017创建Xamarin Forms Master Detail示例时,您将获得一个使用以下方法生成的MockDataStore类

    public async Task<bool> DeleteItemAsync(string id)
    {
        var _item = items.Where((Item arg) => arg.Id == id).FirstOrDefault();
        items.Remove(_item);

        return await Task.FromResult(true);
    }
公共异步任务DeleteItemAsync(字符串id)
{
var\u item=items.Where((item arg)=>arg.Id==Id.FirstOrDefault();
项目。删除(_项);
返回等待任务。FromResult(true);
}
说这是微软的一个例子让人觉得很幼稚,因此它一定是对的

我不明白为什么那些方法不只是
返回true
,而且我还没有看到这个习惯用法的解释。这里是否缺少一些微妙的东西,或者这是一个应该从模板中清除的历史性解决方法?

此方法可以(应该)同步实现,因为它确实是同步的:

public bool DeleteItem(string id)
{
    var _item = items.Where((Item arg) => arg.Id == id).FirstOrDefault();
    items.Remove(_item);

    return true;
}
将同步方法命名为*Async并返回
任务
,这是没有意义的

我想您应该在其中添加自己的异步删除逻辑。毕竟,生成的代码只是示例代码

然后,您将等待实际的数据库操作,而不是
任务。FromResult
(true),即您将
任务。FromResult(true)
替换为对执行数据库查询的方法的异步调用,然后在异步方法成功返回后返回
true

此方法可能(应该)以及同步实施,因为它确实是同步的:

public bool DeleteItem(string id)
{
    var _item = items.Where((Item arg) => arg.Id == id).FirstOrDefault();
    items.Remove(_item);

    return true;
}
将同步方法命名为*Async并返回
任务
,这是没有意义的

我想您应该在其中添加自己的异步删除逻辑。毕竟,生成的代码只是示例代码


然后,您将等待实际的数据库操作,而不是
Task.FromResult
(true),即替换
Task.FromResult(true)
对执行数据库查询的方法进行异步调用,然后在异步方法成功返回后返回
true

TL;DR:当函数返回
Task
Task
时,它将被异步处理。但它本身不需要是
async

使用
async
await
意味着编译器将构建一个状态机来处理此问题。但是,如果等待的只是最后一个表达式,则可以避免使用此状态机:

public Task<bool> DeleteItemAsync(string id)
{
    // Nothing awaitable here...

    return Task.FromResult(true);
}
公共任务DeleteItemAsync(字符串id) { //这里没有什么值得期待的。。。 返回Task.FromResult(true); } 并创建一个同步运行的函数,但由于它对异步行为的调用,因此具有异步函数的特征码和行为

为什么返回
任务
:因为这正是调用者所期望的:如果不一直(可能)更改所有调用者、调用者及其调用者,则无法更改此任务

因此签名无法更改。您必须返回可等待的内容。但如果这是您最后要做的事情,您可以返回另一个结果的“可等待性”(有点像实现尾部递归)

你会得到一个模拟数据存储

因此,这仅用于测试:开销不太可能很大,它提供的代码可以作为真实代码的一个很好的示例进行调整(比提供一个很差示例的框架代码要好得多)


注意:对于C#7,这是一个很好的例子,可以利用它来避免在立即知道结果时分配
任务的开销。

TL;DR:当函数返回
任务
任务
时,它将被异步处理。但它本身不需要是
异步的

使用
async
await
意味着编译器将构建一个状态机来处理此问题。但是,如果等待的只是最后一个表达式,则可以避免使用此状态机:

public Task<bool> DeleteItemAsync(string id)
{
    // Nothing awaitable here...

    return Task.FromResult(true);
}
公共任务DeleteItemAsync(字符串id) { //这里没有什么值得期待的。。。 返回Task.FromResult(true); }
并创建一个同步运行的函数,但由于它对异步行为的调用,因此具有异步函数的特征码和行为

为什么返回
任务
:因为这正是调用者所期望的:如果不一直(可能)更改所有调用者、调用者及其调用者,则无法更改此任务

因此签名无法更改。您必须返回可等待的内容。但如果这是您最后要做的事情,您可以返回另一个结果的“可等待性”(有点像实现尾部递归)

你会得到一个模拟数据存储

因此,这仅用于测试:开销不太可能很大,它提供的代码可以作为真实代码的一个很好的示例进行调整(比提供一个很差示例的框架代码要好得多)


注意:对于C#7,这是一个很好的例子,可以用来避免在结果立即已知时分配
任务的开销。

我想这背后的原因是为了防止“异步方法缺少等待运算符”“编译器警告。此自动生成代码的作者希望将函数标记为
async
,因为在实现真正的功能时,无论如何都要这样做。因此,为了防止编译器警告(没有自动生成的代码会生成编译器警告),您需要等待一些东西,而它们的代码中没有什么可以等待的,因此它们选择等待
任务。FromResult


当然,当您自己编写代码而不是为将来的编辑自动生成代码时,您不需要这样做。

我想这背后的原因是为了防止“async method缺少等待运算符”编译器警告。此自动生成代码的作者希望将函数标记为
async
,因为当