Span<T> and ReadOnlySpan<T> provide high-performance memory views over arrays, stack memory, and strings. They enable efficient slicing and parsing while staying in managed code.
Why it matters
- Reduces allocation pressure in parsing and transformation code.
- Enables fast slicing without copying buffers.
- Improves throughput in hot paths while retaining type safety.
Cautions
Span<T> is a ref struct, so it cannot be stored on the heap, captured by lambdas, or used across await boundaries. Keep span-based logic synchronous and scoped to the current stack frame.
Slice arrays without allocation
Span slices create lightweight views over existing memory instead of new arrays.
Valid since C# 7.2
using System;
int[] values = { 5, 10, 15, 20, 25, 30 };
Span<int> window = values.AsSpan(1, 3);
for (int i = 0; i < window.Length; i++)
{
window[i] *= 2;
}
Console.WriteLine(string.Join(", ", values)); // 5, 20, 30, 40, 25, 30
Use ReadOnlySpan<char> over strings
ReadOnlySpan<char> lets you process substrings without allocating new string instances.
Valid since C# 7.2
using System;
string csv = "alpha,beta,gamma";
ReadOnlySpan<char> text = csv.AsSpan();
int separatorIndex = text.IndexOf(',');
ReadOnlySpan<char> firstToken = text[..separatorIndex];
ReadOnlySpan<char> remainder = text[(separatorIndex + 1)..];
Console.WriteLine(firstToken.ToString()); // alpha
Console.WriteLine(remainder.ToString()); // beta,gamma
Related features
Learn more
Newer capabilities
-
More implicit span conversions
Introduced in C# 14.0
C# 14 expands implicit conversions among
Span<T>andReadOnlySpan<T>scenarios, reducing ceremony when passing slices into APIs that accept read-only views.