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.