【问题标题】:How to return async IEnumerable<string>?如何返回异步 IEnumerable<string>?
【发布时间】:2019-05-07 12:25:05
【问题描述】:

我有以下方法:

public async IEnumerable<string> GetListDriversAsync()
{
   var drives = await graphClient.Drive.Root.Children.Request().GetAsync();
        foreach (var d in drives)
            yield return d.ToString(); 
}

但是编译器错误提示:

"async 的返回类型必须为 void,Task 或 Task &lt;T&gt;"

方法异步时如何返回 IEnumerable?

【问题讨论】:

  • 将你的方法签名重命名为public async Task&lt;IEnumerable&lt;string&gt;&gt; GetListDriversAsync()
  • 我已经试过了,它说:“主体不能是迭代器,因为 Task> 不是接口类型”
  • 简短的回答是,在当前版本的 C# 中无法完成您想做的事情。如果将迭代器方法封装在本地函数中,则可以保留它,但您需要完全填充集合并返回它以使用 async 关键字和 Task&lt;T&gt; 返回类型。目前不支持“async yield return”。
  • 您正在尝试做的是“异步枚举” - 这是一个 vNext 功能;现在:没有很好的选择

标签: c#


【解决方案1】:

C# 8 中可以使用另一种方法。它使用IAsyncEnumerable

public async IAsyncEnumerable<string> GetListDriversAsync()
{
    var drives = await graphClient.Drive.Root.Children.Request().GetAsync();
    foreach (var d in drives)
        yield return d.ToString();
}

它会稍微改变您的签名,这可能(也可能不是)适合您。

用法:

await foreach (var driver in foo.GetListDriversAsync())
{
    Console.WriteLine(driver );
}

【讨论】:

    【解决方案2】:

    试试这个:

    public async Task<IEnumerable<string>> GetListDriversAsync()
    {
        var drives = await graphClient.Drive.Root.Children.Request().GetAsync();
    
        IEnumerable<string> GetListDrivers()
        {
            foreach (var d in drives)
                yield return d.ToString();
        }
    
        return GetListDrivers();
    }
    

    【讨论】:

    • 只是为了我自己的理解-为什么在这种情况下使用本地函数和yield return而不是return drives.Select(d =&gt; d.ToString())
    • @ScottHannen 请参阅Local functions and exceptions,其中讨论了与本地函数相关的枚举器异常处理
    • @ScottHannen - OP 想要yield 所以这就是我这样写的原因。 Marathon55 也认为它是处理异常的正确模式。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-10
    • 1970-01-01
    • 1970-01-01
    • 2014-03-19
    • 2019-08-17
    • 2014-12-03
    相关资源
    最近更新 更多