Search code examples
c#state-machinec#-9.0iasyncenumerable

Why are async methods, which return an IAsyncEnumerable, implemented as classes instead of structs?


I am curious to why async methods returning an IAsyncEnumerable compile down to a state machine, which is defined as a class instead of a struct as it usually is. See the following example:

public async IAsyncEnumerable<int> MethodOne() 
{ 
    await Task.Delay(10);
    yield return 0;
}

// Compiled version

[CompilerGenerated]
private sealed class <MethodOne>d__0 : IAsyncEnumerable<int>, IAsyncEnumerator<int>,
    IAsyncDisposable, IValueTaskSource<bool>, IValueTaskSource, IAsyncStateMachine
{
    // Omitted for brevity 
}

Sharplab.io

public async Task<int> MethodTwo() 
{ 
    await Task.Delay(10);
        
    return 0;
}

// Compiled version

[StructLayout(LayoutKind.Auto)]
[CompilerGenerated]
private struct <MethodTwo>d__0 : IAsyncStateMachine
{
    // Omitted for brevity 
}

Sharplab.io


Solution

  • The state machine itself implements IAsyncEnumerable<T>, and is newed up and returned as the IAsyncEnumerable<T> instance. If it was a struct type, it would be immediately boxed by the conversion to an interface type anyway.