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
reflocals still cannot be live across ayield returnorawaitexpressionunsafecode blocks are allowed but cannot containyieldorawait- Enables more natural use of
Span<T>andrefin async and iterator methods