yield оператор в async методе без IAsyncEnumerable
Как мне возвращать значение через yield в асинхронном методе БЕЗ использования IAsyncEnumerable?
public async Task<IEnumerable<MyClass>> MyEnumerableMethod()
{
foreach(var item in smthCollection)
{
yield return item; //CS1624 Task<IEnumerable<MyClass>> is not an iterator interface type
}
}
Ответы (3 шт):
Есть 2 варианта использования итератора, позволяющие применять ключевое слово yield:
Синхронный
IEnumerable<T>
IEnumerator<T>
И асинхронный
async IAsyncEnumerable<T>
async IAsyncEnumerator<T>
Больше никаких вариантов сигнатур нет, это ограничение зашито на уровне языка C#.
В вашем примере нет await, да и вообще не совсем понятно чего вы пытаетесь добиться. Но если предположить, что до вашего цикла есть какая-то асинхронная операция, то можно цикл вынести в отдельный локальный метод, тогда у вас будет возможность использовать yield return, т.к. этот будет не асинхронный. Например:
async Task<IEnumerable<int>> Test()
{
var smthCollection = await GetSmth();
return Get(smthCollection);
IEnumerable<int> Get(IEnumerable<int> smthCollection)
{
foreach(var item in smthCollection)
{
// что-то делаем с item
yield return item;
}
}
}
Но тогда у лучше использовать IAsyncEnumerable<T>. А так да, я согласен, что использовать async и yield без IAsyncEnumerable<T> нельзя.
Проблема в том, что Task<IEnumerable<MyClass>> должен возвращать одну задачу, внутри которой завёрнут IEnumerable (и один из ответов показывает, как это можно сделать).
Когда используется return, то C# сам оборачивает возвращаемое значение в Task, а что вы хотите обернуть в Task, когда делаете yield return, компилятору непонятно - это должно быть много Task-ов или что? Поэтому так нельзя.