从异步方法返回IAsyncEnumerable [英] Return IAsyncEnumerable from an async method

查看:389
本文介绍了从异步方法返回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;
   }
}

我想知道,上面的代码试图做的最佳实践是什么.基本上是从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:

  1. 遍历IAsyncEnumerable并立即返回结果.
  1. Iterating over the IAsyncEnumerable and yielding the result immediately back.

await foreach(var item in Bar())
{
    yield return item;
}

  1. 创建一个可以临时存储IAsyncEnumerable的结构,这似乎是更好的解决方案,但仍然有些过头.
  1. 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)的建议使用awaityield:

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆