Skip to content

allows ref struct C# 13.0performancenew scenarios

Allow ref struct types to be used as generic type arguments.

Generic type parameters could not accept ref struct types like Span<T> or ReadOnlySpan<T>. This meant high-performance code using spans could not participate in generic abstractions that preserved stack-only lifetime rules.

C# 13 introduces the allows ref struct anti-constraint, enabling generic type parameters to accept ref struct types while the compiler enforces the necessary lifetime restrictions.

Code

csharp
interface IReadOnlyIntBuffer
{
    int Length { get; }
    int this[int index] { get; }
}

ref struct IntSpanBuffer(ReadOnlySpan<int> values) : IReadOnlyIntBuffer
{
    public int Length => values.Length;
    public int this[int index] => values[index];
}

static int Sum<TBuffer>(scoped TBuffer buffer)
    where TBuffer : IReadOnlyIntBuffer, allows ref struct
{
    var result = 0;
    for (var i = 0; i < buffer.Length; i++)
        result += buffer[i];
    return result;
}

var total = Sum(new IntSpanBuffer([1, 2, 3, 4, 5]));
csharp
// Could not use a ref struct as a generic type argument.
// You had to write overloads for each stack-only buffer shape.
static int Sum(ReadOnlySpan<int> values)
{
    var result = 0;
    foreach (var value in values)
        result += value;
    return result;
}

Notes

  • allows ref struct is an anti-constraint that relaxes the default restriction rather than adding one
  • The compiler ensures ref struct values are not used in ways that would violate their lifetime rules (e.g. boxing, storing in fields of non-ref struct types)
  • Enables the BCL to offer Span<T>-based overloads in generic APIs

More information