C# value types can be allocated on either the stack or the heap, depending on usage. However, some high-performance scenarios require guaranteeing that a type never escapes to the heap to avoid garbage collection overhead.
C# 7.2 introduces ref struct
, a special kind of value type that can only be allocated on the stack. This enables zero-allocation scenarios and is the foundation for types like Span<T>
which provide safe, high-performance access to memory.
Code
C#
ref struct SpanLike<T>
{
private readonly Span<T> _data;
public SpanLike(Span<T> data)
{
_data = data;
}
public ref T this[int index] => ref _data[index];
}
void ProcessData()
{
Span<int> numbers = stackalloc int[100];
var span = new SpanLike<int>(numbers);
span[0] = 42; // Fast, stack-only access
}
C#
struct SpanLike<T>
{
private readonly T[] _data;
public SpanLike(T[] data)
{
_data = data; // Must use heap-allocated array
}
public ref T this[int index] => ref _data[index];
}
void ProcessData()
{
var numbers = new int[100]; // Heap allocation
var span = new SpanLike<int>(numbers);
span[0] = 42;
}
Notes
- Ref structs cannot be boxed, used as generic type arguments, or assigned to interfaces
- They cannot be fields of non-ref struct types or appear in async methods or iterators
- Ref structs cannot implement interfaces or be used in lambda expressions or local functions that capture them
- The most common ref struct in .NET is
Span<T>
which enables safe, efficient memory access - Use ref structs when you need guaranteed stack-only allocation for performance-critical code