When building high-performance .NET applications, reducing memory allocations can significantly improve performance and lower garbage collection (GC) pressure.
That’s where Span<T> and Memory<T> come in.
Although they look similar, they are designed for different scenarios. Understanding when to use each can help you write faster and more memory-efficient applications.
What is Span<T>?
Span<T> is a lightweight type that provides a safe and efficient view over a contiguous region of memory.
Instead of creating a copy of an array or string, it lets you work with the existing memory directly.
Example:
int[] numbers = { 10, 20, 30, 40, 50 };
Span<int> firstThree = numbers.AsSpan(0, 3);
foreach (var number in firstThree)
{
Console.WriteLine(number);
}
No new array is created.
The span simply references the existing memory.
Why is Span<T> Fast?
Normally, slicing an array creates another array.
var copy = numbers[0..3];
This allocates additional memory.
Using Span<T>:
Span<int> slice = numbers.AsSpan(0, 3);
No allocation.
No copying.
Less GC pressure.
Important Limitation of Span<T>
Span<T> is a stack-only type (ref struct).
Because of this:
- It cannot be stored in a class field.
- It cannot be boxed.
- It cannot implement interfaces.
- It cannot be used across
awaitoryieldboundaries.
These restrictions exist to ensure memory safety.
What is Memory<T>?
Memory<T> represents the same concept as Span<T>, but it can safely live on the managed heap.
This means it works well in asynchronous and long-lived scenarios.
Example:
Memory<byte> buffer = new byte[4096];
await ProcessAsync(buffer);
Inside the async method:
public async Task ProcessAsync(Memory<byte> memory)
{
await Task.Delay(100);
Span<byte> span = memory.Span;
// Process data
}
Memory<T> survives across await, while Span<T> cannot.
Span vs Memory
| Feature | Span | Memory |
|---|---|---|
| Stack-only | โ | โ |
| Heap allocation | โ | โ |
| Works with async | โ | โ |
| Can be stored in fields | โ | โ |
| Best for | Synchronous operations | Asynchronous operations |
When Should You Use Each?
Use Span<T> when:
- Processing arrays
- Parsing strings
- Working synchronously
- Optimizing performance-critical code
Use Memory<T> when:
- Working with async methods
- Long-lived buffers
- Pipelines
- Network programming
- File I/O
Real-World Examples
Span<T> is commonly used in:
- String parsing
- Serialization
- JSON processing
- High-performance algorithms
Memory<T> is commonly used in:
- ASP.NET Core
- System.IO.Pipelines
- Networking
- Streaming large files
Final Thoughts
Span<T> and Memory<T> are powerful additions to modern .NET that help developers write faster, allocation-efficient code.
The rule is simple:
- Need fast, synchronous access? Use
Span<T>. - Need async or long-lived memory? Use
Memory<T>.
Choosing the right type can reduce allocations, improve performance, and make your applications more scalable.

Leave a Reply