`Memory<T>` & `ReadOnlyMemory<T>`: Heap-Safe Async Spans
1Concept
Because `Span<T>` is a `ref struct`, it cannot cross `await` boundaries or live in async state machine fields. `Memory<T>` is a standard heap-safe struct that can be stored in classes and sliced across asynchronous tasks.
2Architecture Diagram
[ Memory<byte> (Heap-Safe) ] ──> Stored in class / Passed across `await`
│
.Span Property
▼
[ Span<byte> (Stack-Only) ] ──> Ultra-fast in-memory parsing on current thread3Code Example
C# 13 & .NET 9
using System;
using System.Threading.Tasks;
public class MemoryAsyncDemo
{
public static async Task ProcessBufferAsync(ReadOnlyMemory<byte> memory)
{
// Safe to pass across await boundaries!
await Task.Delay(5);
// Convert to Span for fast synchronous parsing
ReadOnlySpan<byte> span = memory.Span;
Console.WriteLine($"Async Buffer Processed: {span.Length} bytes.");
}
public static async Task Main()
{
byte[] data = [0x01, 0x02, 0x03, 0x04, 0x05];
await ProcessBufferAsync(data.AsMemory(1, 3));
}
}4Expected Output
Async Buffer Processed: 3 bytes.
5Key Takeaways
- ✓Use `Memory<T>` in async methods and class fields.
- ✓Access `.Span` only when you are ready to perform synchronous operations on the current thread.
- ✓Slicing `Memory<T>` (`memory.Slice(start, len)`) is non-allocating.