C# Ref Struct — Complete Guide
In this tutorial, you'll learn about C# Ref Struct. We cover key concepts, practical examples, and best practices.
You create a small struct to hold temporary data, but it can still end up on the heap — boxed, as a field of a class, or in an array. ref struct guarantees the type lives only on the stack, never on the heap. This enables safe use of Span<T> and other stack-dependent types.
Wrong
public struct BufferWrapper
{
public Span<byte> Data; // CS8345: Span cannot be a field of a non-ref-struct
}
Output: Compiler error CS8345. Span<T> can only be a field of a ref struct.
Right
public ref struct BufferWrapper
{
public Span<byte> Data { get; init; }
}
// Usage — only on the stack
Span<byte> buffer = stackalloc byte[256];
var wrapper = new BufferWrapper { Data = buffer };
Process(ref wrapper);
Output: Compiles. BufferWrapper is a stack-only type, so it can safely hold a Span<T>.
ref struct restrictions:
- Cannot be boxed (no
object,interface,dynamic) - Cannot be a field of a class or non-ref struct
- Cannot be used in async methods, lambdas, or iterators
- Cannot be a generic type argument
- Can implement
IDisposable(forusing)
public ref struct Transformer
{
private Span<byte> _buffer;
public Transformer(Span<byte> buffer) => _buffer = buffer;
public void Dispose() => _buffer.Clear();
}
Prevention
- Use
ref structto holdSpan<T>orReadOnlySpan<T>fields. - Use
ref structfor performance-sensitive temporary types. - Use
readonly ref structfor immutable stack-only types. - Use
ref structwithIDisposablefor deterministic cleanup viausing. - Use
ref structwithscopedparameters to limit escape scope. - Avoid
ref structfor types that need heap storage, async, or generics.
Common Mistakes with ref struct
- Misunderstanding that
Stringis[Char]with poor performance for large text operations - Using
foldlinstead offoldl'causing stack overflow on large lists - Forgetting
deriving (Show, Eq)on custom data types needed for debugging
These mistakes appear frequently in real-world CSHARP code. DodaTech's contributors have identified these patterns through analysis of open-source projects and production systems.
Practice Exercise
Write a pure function that safely divides two integers using Maybe, then test it with edge cases like division by zero and negative numbers.
This exercise reinforces the concepts covered in this guide. Try implementing it before checking online solutions.
FAQ
ref struct is fundamental to Span<T> and is used extensively in Durga Antivirus Pro's zero-allocation parsing engine. For more C#, visit DodaTech.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro