What are Span<T> and Memory<T> in C#, and when should you use them?
cs-sen-004
Your answer
Answer as you would in a real interview — explain your thinking, not just the conclusion.
Model answer
Span<T> is a ref struct that provides a type-safe, bounds-checked view over contiguous memory — a managed array, a stack-allocated block, or native memory — without copying. Because it is a ref struct, it can only live on the stack, which means it cannot be stored in a field, boxed, or used across await points. Memory<T> is the heap-friendly sibling: it can be stored as a field and crosses async boundaries, then you call .Span on it when you need the Span. Together they eliminate the 'allocate a substring' pattern: instead of string.Substring (allocates), you take a ReadOnlySpan<char> slice. Use them in parsing, serialisation, and network I/O hot paths where allocations are measurable.
Code example
// Parse comma-separated ints with zero allocations
public static IEnumerable<int> ParseInts(ReadOnlySpan<char> input)
{
while (!input.IsEmpty)
{
int comma = input.IndexOf(',');
var token = comma == -1 ? input : input[..comma];
if (int.TryParse(token, out int value))
yield return value; // can't yield inside Span method:
// use a List or a different pattern
input = comma == -1 ? ReadOnlySpan<char>.Empty : input[(comma + 1)..];
}
}
// Zero-copy stack allocation
Span<byte> buffer = stackalloc byte[256];
int written = FillBuffer(buffer);
SendToNetwork(buffer[..written]);
// Memory<T> across async (Span cannot cross await)
public async Task ProcessAsync(Memory<byte> mem)
{
await Task.Delay(10); // OK — Memory is heap-safe
ReadOnlySpan<byte> view = mem.Span; // get Span for local work
}
Follow-up
How does MemoryPool<T> compare to ArrayPool<T>? When would you choose one over the other?