Skip to content

ref and unsafe in iterators and async C# 13.0performancenew scenarios

Allow ref locals and unsafe blocks in iterator and async methods.

Iterator methods (using yield) and async methods (using await) previously banned all use of ref locals and unsafe code, even in sections that did not cross a yield or await boundary. This forced developers to refactor code into separate helper methods.

C# 13 relaxes these restrictions. ref locals and unsafe blocks are now allowed as long as they do not span a yield return or await expression.

Code

C#
IEnumerable<int> DoubleValues(int[] values)
{
    foreach (var value in values)
    {
        ref var item = ref Unsafe.AsRef(in value);
        yield return item * 2;
    }
}

async Task ProcessAsync(int[] data)
{
    Span<int> buffer = stackalloc int[10];
    Fill(buffer);

    await SendAsync(buffer.ToArray());
}
C#
IEnumerable<int> DoubleValues(int[] values)
{
    // ref locals were not allowed at all in iterator methods
    // even though they don't cross a yield boundary
    foreach (var value in values)
    {
        var item = value;
        yield return item * 2;
    }
}

async Task ProcessAsync(int[] data)
{
    // Span and stackalloc were not allowed in async methods
    var buffer = new int[10];
    Fill(buffer);

    await SendAsync(buffer);
}

Notes

  • ref locals still cannot be live across a yield return or await expression
  • unsafe code blocks are allowed but cannot contain yield or await
  • Enables more natural use of Span<T> and ref in async and iterator methods

More information