首页 > 解决方案 > 从异步方法返回 IAsyncEnumerable

问题描述

采取以下方法:

public async IAsyncEnumerable<int> Foo()
{
   await SomeAsyncMethod();
   return Bar(); // Throws since you can not return values from iterators
}

public async IAsyncEnumerable<int> Bar()
{
   for(int i = 0; i < 10; i++)
   {
       await Task.Delay(100);
       yield return i;
   }
}

我想知道最佳实践是什么,做什么,上面的代码试图做什么。基本上IAsyncEnumerableasync方法返回一个。

对于我自己,我可以想象两种方式:

  1. 迭代IAsyncEnumerable并立即返回结果。
await foreach(var item in Bar())
{
    yield return item;
}
  1. 创建一个可以IAsyncEnumerable临时存储的结构,这似乎是更好的解决方案,但仍然有点矫枉过正。
return new AsyncEnumerableHolder<int>(Bar());

public struct AsyncEnumerableHolder<T>
{
    public readonly IAsyncEnumerable<T> Enumerable;

    public AsyncEnumerableHolder(IAsyncEnumerable<T> enumerable)
    {
        Enumerable = enumerable;
    }
}

有没有更好的方法来实现这种行为?

标签: c#async-awaitc#-8.0iasyncenumerable

解决方案


struct 方法行不通。如果你想异步返回一个IAsyncEnumerator<T>值,你可以使用Task<IAsyncEnumerator<T>>with return Bar();。然而,这将是不寻常的。在异步可枚举的开头创建一个新IAsyncEnumerator<T>的合并会更自然。await SomeAsyncMethod()为此,您应该按照选项 (1) 的建议使用await和:yield

public async IAsyncEnumerable<int> Foo()
{
  await SomeAsyncMethod();
  await foreach (var item in Bar())
    yield return item;
}

yield*附带说明一下,对于这种“将整个序列枚举到我的结果序列”概念,JavaScript 有一个非常好的语法,它支持同步和异步序列。C# 没有这种用于同步或异步序列的语法。


推荐阅读