ref struct
Implements Interfaces in C# 13 — A New Era for High-Performance Abstractions
C# 13 brings a breakthrough for systems-level and performance-oriented developers: ref struct
types can now implement interfaces.
For years, ref struct
types like Span<T>
were powerful but isolated — unable to participate in polymorphism, generic contracts, or interface-based architecture. That changes now, with safe and scoped interface implementation.
But there’s a twist: no boxing allowed. Let’s dive in.
What’s a ref struct
Again?
A ref struct
is a stack-only, memory-safe value type. Examples:
Span<T>
ReadOnlySpan<T>
-
ref struct
-based buffer parsers, writers, etc.
They cannot:
- Be boxed
- Be captured in lambdas
- Be used across
await
/yield
Until C# 13, they also could not implement interfaces — meaning no IComparable
, IDisposable
, or IEnumerable
.
What’s New in C# 13?
Now you can do:
public interface IPrinter
{
void Print();
}
public ref struct Logger : IPrinter
{
public void Print() => Console.WriteLine("Logger active.");
}
✅ Implements the interface
❌ Cannot be cast to IPrinter
directly
✅ Can be accessed through generic constraints
Why Can’t You Cast to Interface?
IPrinter printer = new Logger(); // ❌ Compilation error
This would require boxing — which moves the value to the heap and breaks the ref safety model.
Rule: ref struct
types can implement interfaces, but they cannot be converted to them.
How To Access Interface Members
Via Generic Constraint
public static void Process<T>(T tool) where T : allows ref struct, IPrinter
{
tool.Print(); // ✅ Fully safe
}
Now you can write zero-allocation, polymorphic code over ref struct
types!
Example: Safe High-Performance API
public interface IOperation
{
int Run();
}
public ref struct FastAdd : IOperation
{
private int _a, _b;
public FastAdd(int a, int b) => (_a, _b) = (a, b);
public int Run() => _a + _b;
}
public static class Executor
{
public static int Execute<T>(scoped T op)
where T : allows ref struct, IOperation
=> op.Run();
}
// Usage
var add = new FastAdd(3, 4);
Console.WriteLine(Executor.Execute(add)); // Outputs: 7
✅ No heap allocations
✅ No boxing
✅ Interface reuse, generic flexibility, ref-safe
Summary of Rules
Feature | Supported in C# 13? | Notes |
---|---|---|
ref struct implements interface |
✅ Yes | Must implement all members |
Default interface methods | ✅ Yes | Must still be explicitly implemented |
Interface casts ((IPrinter)x ) |
❌ No | Boxing disallowed |
Access via where T : allows ref struct, IInterface
|
✅ Yes | Enables safe generic-based access |
Learn More
Final Thoughts
C# 13 removes a key limitation for ref struct
types, enabling them to participate in interface-based designs without compromising on ref safety or performance.
By combining allows ref struct
with generic constraints, you can now build high-performance APIs that compose like interfaces, but run like native code.
You get zero allocations, type safety, and full architectural reuse — all while staying on the stack.
Written by: [Cristian Sifuentes] – Systems-Level .NET Developer | Span Architect | Safety-First Code Designer
Will this help you refactor low-level performance code into reusable components? Let's talk!
Top comments (1)
I am not sure how converting a string to a span and then iterating over the characters is going to be more performant