Вернуть IAsyncEnumerable из метода asyn c - PullRequest
2 голосов
/ 11 января 2020

Возьмите следующие методы:

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;
   }
}

Интересно, что было бы лучше всего делать, как пытается описанный выше код. В основном, возвращая IAsyncEnumerable из async метода.

Для себя я могу представить два пути:

  1. Итерация по IAsyncEnumerable и немедленный возврат результата.
await foreach(var item in Bar())
{
    yield return item;
}
Создание структуры, которая может временно хранить IAsyncEnumerable, что кажется лучшим решением, но все же является излишним.
return new AsyncEnumerableHolder<int>(Bar());

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

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

Есть ли лучший способ добиться такого поведения?

1 Ответ

4 голосов
/ 11 января 2020

Структурный подход не сработает. Если вы хотите асинхронно вернуть значение IAsyncEnumerator<T>, вы можете использовать Task<IAsyncEnumerator<T>> с return Bar();. Однако это было бы необычно. Было бы гораздо более естественным создать новый IAsyncEnumerator<T>, который включает await SomeAsyncMethod() в начале асинхронного перечислимого. Чтобы сделать это, вы должны использовать await и yield, как предложено вашим вариантом (1):

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

В примечании стороны, JavaScript имеет очень хороший синтаксис yield* для этого своего рода концепция «перечислить всю эту последовательность в мою последовательность результатов», и она поддерживает как синхронные, так и асинхронные последовательности. C# не имеет такого синтаксиса ни для синхронных, ни для асинхронных последовательностей.

...