0

I try to use an AsyncEnumerable that returns a list of items in each yield and try to use SelectMany (or SelectManyAsync) to retrieve all items.

Working sample:

IAsyncEnumerable<IReadOnlyList<...>> source = ...;
await foreach (var list in source)
{
    foreach (var item in list)
    {
        // Perform some action on item
    }
}

But I try to use linq for that like:

IAsyncEnumerable<IReadOnlyList<...>> source = ...;
var items = from list in source
            from item in list
            where ...
            select item;
await foreach (var item in items)
{
    ...
}

Or in method syntax:

IAsyncEnumerable<IReadOnlyList<...>> source = ...;
var items = source
    .SelectMany(static list => list)
    .Where(...);
await foreach (var item in items)
{
    ...
}

But I got an error from compiler:

CS0411: The type arguments for Method 'AsyncEnumerable.SelectMany....)' cannot be inferred from usage.

Is there any way to use the synchronous linq extensions after awaiting the AsyncEnumerable or is the working sample the only way of handling such problems?

EDIT

What I'm looking for is an extension method like the following one that is supported by linq query syntax:

public static async IAsyncEnumerable<T> SelectMany<TCollection, T>(this IAsyncEnumerable<TCollection> self, Func<TCollection, IEnumerable<T>> selector)
    where TCollection : IEnumerable<T>
{
    await foreach (var collection in self)
    {
        foreach (var item in selector(collection))
        {
            yield return item;
        }
    }
}

Is there any extension method like this one?

Sebastian Schumann
  • 3,204
  • 19
  • 37
  • 1
    Does this answer your question? [Linq methods for IAsyncEnumerable](https://stackoverflow.com/questions/58376585/linq-methods-for-iasyncenumerable) – Roe Mar 06 '23 at 11:11
  • @Roe Not really. They only provide extensions that have to return a new `IAsyncEnumerable`. In my sample the items are `IEnumerable<>`. And I didn't find any sample for my problem. There are much samples for `SelectMany(async () => await ...)` - but that's not my case. – Sebastian Schumann Mar 06 '23 at 11:16
  • 3
    @SebastianSchumann youre not making much sense. You cant return `IEnumerable` from `SelectMany` and then expect to asynchronously await over the collection in a `await foreach` loop? `SelectMany` returns `IAsyncEnumerable` because the original collection is `IAsyncEnumerable`. Why would you want to turn an asynchronous enumerable into a synchronous enumerable? – Kieran Devlin Mar 06 '23 at 11:40
  • @KieranDevlin I don't want to turn from `AsyncEnumerable` to `Enumerable`. I've an `AsyncEnumerable` where each item is a list. I try to use linq. There is no loop over `source` until the `await foreach`. My thougth were to add synchronous linq extensions to the `AsyncEnumerable` that doesn't change the asynchrounous behaviour. After that I tried to iterate using `await foreach`. – Sebastian Schumann Mar 06 '23 at 12:24
  • @KieranDevlin Please see my edit. I created an extension method that does what I want but is not recognized from linq in query syntax. And please notice that this method performs a synchronous `SelectMany` over an `AsyncEnumerable` and still returns an `AsyncEnumerable`. There is no conversion from `AsyncEnumerable` to Non-Async-`Enumerable`. – Sebastian Schumann Mar 06 '23 at 12:34

1 Answers1

3

using <PackageReference Include="System.Linq.Async" Version="6.0.1" />

IAsyncEnumerable<IReadOnlyList<string>> source = new[] { new[] { "1", "2" } }.ToAsyncEnumerable();
var result = source.SelectMany(list => list.ToAsyncEnumerable());
await foreach (var s in result)
{
    Console.WriteLine(s);
}
Magnus
  • 45,362
  • 8
  • 80
  • 118