从异步方法返回IAsyncEnumerable [英] Return IAsyncEnumerable from an async method
问题描述
采用以下方法:
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;
}
}
我想知道,上面的代码试图做的最佳实践是什么.基本上是从async
方法返回IAsyncEnumerable
.
I wonder what the best practice would be, to do, what the code above tries to. Basically returning an IAsyncEnumerable
from an async
method.
我自己可以想象两种方式:
For myself I can imagine two ways:
- 遍历
IAsyncEnumerable
并立即返回结果.
- Iterating over the
IAsyncEnumerable
and yielding the result immediately back.
await foreach(var item in Bar())
{
yield return item;
}
- 创建一个可以临时存储
IAsyncEnumerable
的结构,这似乎是更好的解决方案,但仍然有些过头.
- Creating a struct which can store an
IAsyncEnumerable
temporarily, which seems to be the better solution, but still kind of overkill.
return new AsyncEnumerableHolder<int>(Bar());
public struct AsyncEnumerableHolder<T>
{
public readonly IAsyncEnumerable<T> Enumerable;
public AsyncEnumerableHolder(IAsyncEnumerable<T> enumerable)
{
Enumerable = enumerable;
}
}
有没有更好的方法来实现这种行为?
Is there any better way to achieve this behavior?
推荐答案
结构方法无效.如果要异步返回IAsyncEnumerator<T>
值,则可以将Task<IAsyncEnumerator<T>>
与return Bar();
一起使用.但是,那是不寻常的.创建一个新的IAsyncEnumerator<T>
并在异步枚举的开始处合并await SomeAsyncMethod()
会更加自然.为此,应按照选项(1)的建议使用await
和yield
:
The struct approach wouldn't work. If you want to asynchronously return an IAsyncEnumerator<T>
value, you could use Task<IAsyncEnumerator<T>>
with return Bar();
. However, that would be unusual. It would be much more natural to create a new IAsyncEnumerator<T>
that incorporates await SomeAsyncMethod()
at the beginning of the asynchronous enumerable. To do this, you should use await
and yield
as suggested by your option (1):
public async IAsyncEnumerable<int> Foo()
{
await SomeAsyncMethod();
await foreach (var item in Bar())
yield return item;
}
另一方面,对于这种将整个序列枚举到我的结果序列中"的概念,JavaScript具有非常好的yield*
语法,它支持同步和异步序列.对于同步或异步序列,C#没有这种语法.
On a side note, JavaScript has a very nice yield*
syntax for this kind of "enumerate this whole sequence into my result sequence" concept, and it supports both synchronous and asynchronous sequences. C# does not have this kind of syntax for either synchronous or asynchronous sequences.
这篇关于从异步方法返回IAsyncEnumerable的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!