In recent .NET releases, Span<T> and Memory<T> have become essential tools for high‑performance scenarios. This post explores their differences, when to use each, and provides practical examples.
What is Span<T>?
Span<T> is a stack‑only type that provides a view over contiguous memory. It can reference arrays, String, or even unmanaged memory. Because it's a ref struct, it cannot be boxed or captured by async lambdas.
void ProcessData(ReadOnlySpan<byte> data)
{
for (int i = 0; i < data.Length; i++)
{
// Process each byte...
}
}
What is Memory<T>?
Memory<T> is the heap‑compatible counterpart of Span<T>. It can be stored, passed around async methods, and used where a ref struct is not allowed. To access its contents, you retrieve a Span<T> via Memory<T>.Span.
async Task<int> ReadFileAsync(string path)
{
var memory = new Memory<byte>(new byte[4096]);
using var stream = File.OpenRead(path);
int read = await stream.ReadAsync(memory);
// Work with memory.Span here...
return read;
}
When to choose one over the other?
- Use
Span<T>for short‑lived, high‑performance code that stays on the stack. - Use
Memory<T>when you need to store the reference or use it asynchronously.
Both types dramatically reduce allocations compared to traditional arrays or strings, especially in parsers and serializers.
Comments (3)
Span<T>extremely useful in my JSON parser.Memory<T>withIAsyncEnumerable?Span<T>in public APIs; it forces callers to use ref structs.