Nesting IAsyncEnumerable I am trying to work around the problem Pass-through for IAsyncEnumerable. The best I have so far is to return IAsyncEnumerable&lt;IAsyncEnumerable&lt;T&gt;&gt; instead of IAsyncEnumerable&lt;T&gt;, then to flatten it. I'm not thrilled about it, so I'm asking here for suggestions. 

The underlying goal is to allow one to get portions of one's IAsyncEnumerable from child methods without going insane. The Counting() method below is my attempt.

I don't think it would be much trouble to design a recursive object in order to allow deeper nesting. But I still don't think I would like it much.

public static class AsyncEnumerables
{
    public static async IAsyncEnumerable&lt;T&gt; Flatten&lt;T&gt;(IAsyncEnumerable&lt;IAsyncEnumerable&lt;T&gt;&gt; enumerables)
    {
        await foreach (var e in enumerables)
        {
            await foreach (var t in e)
            {
                yield return t;
            }
        }
    }

    public static async IAsyncEnumerable&lt;T&gt; Singleton&lt;T&gt;(T t)
    {
        await Task.CompletedTask;
        yield return t;
    }
}

public class AsyncEnumerableTests
{
    public async IAsyncEnumerable&lt;int&gt; Children()
    {
        yield return 1;
        await Task.Delay(1000);
        yield return 2;
    }

    public async IAsyncEnumerable&lt;IAsyncEnumerable&lt;int&gt;&gt; Counting()
    {
        yield return AsyncEnumerables.Singleton(0);
        await Task.Delay(100);
        yield return Children();
        yield return AsyncEnumerables.Singleton(3);
    }

    [Fact]
    public async Task Counting_Counts()
    {
        var numbers = new List&lt;int&gt;();
        await foreach (var n in AsyncEnumerables.Flatten(Counting())) {
            numbers.Add(n);
        }
        Assert.Equal(4, numbers.Count);
        for (int i=0; i&lt;4; i++)
        {
            Assert.Equal(i, numbers[i]);
        }
    }
}
There are several things worth considering when you are about to design an API, which should either return an IAsyncEnumerable&lt;IAsyncEnumerable&lt;T&gt;&gt; or return an IAsyncEnumerable&lt;T&gt;

IAsyncEnumerable &lt; IAsyncEnumerable &lt; T > >

Pros


It is flexible from the consumer point of view. It allows you to use a single or multiple consumer model
In case of multiple consumers the throughput can be higher, because the parallel processing potential
It allows to use different Timeouts for different providers
It allows custom code injection between two yield return statements


Cons


In case of single consumer the ingestion logic can be a bit more complicated (compared to the flatten version)
Nested async loops can complicate the exception handling logic (and also the debugging)


IAsyncEnumerable &lt; T >

Pros


It is easier to use for a single consumer
If the multiple provider model is just an implementation detail then it can hide this information behind a good abstraction
It provides easier error handling capabilities


Cons


It is harder to support multiple consumers model
It is harder to inject custom code between yield returns
Spanning new processing based on different providers is impossible 


If you are considering to provide a flattened API then I would suggest to check that package, which is called System.Interactive.Async. Inside this package there is a class called AsyncEnumerableEx which defines a Merge function.