Phase 19 of 30 · Topic 19.2

`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 thread

3Code 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.