Regra de ouro: Span<T> e ReadOnlySpan<T> vivem apenas na stack (ref struct). Nunca podem ser campos de classes, boxed ou usados em async/await. Para o heap, use Memory<T>.

Stack vs Heap

apontaStackint x = 5Span<byte> sHeapstring objbyte[] arraySpan<T> aponta para memoria contigua sem alocacao
AspectoStackHeap
Quem alocaCompilador (automatico por frame)Runtime / GC (new, boxing)
Quem liberaAutomatico ao sair do metodoGarbage Collector
O que vive laValue types locais, parametros, ponteiros de retornoObjetos (class), arrays, strings, boxed values
PerformanceMuito rapida - move stack pointerDepende do GC - pode causar pausas
Tamanho tipico~1 MB por threadLimitado pela RAM
LifetimeEscopo do metodoEnquanto houver referencia (GC decide)

Value Types vs Reference Types

TipoExemplosOnde moraCopia
Value Typeint, bool, double, struct, enumStack (se local) ou inline no objetoCopia o valor inteiro
Reference Typeclass, string, object, array, delegateHeap (referencia na stack)Copia apenas a referencia

stackalloc - buffer na stack

// stackalloc cria buffer na stack - sem GC Span<byte> buffer = stackalloc byte[256]; buffer[0] = 0xFF; // buffer e liberado automaticamente ao sair do metodo // Use para buffers pequenos (<= poucos KB) // Buffers grandes causam StackOverflowException Span<int> numbers = stackalloc int[4] { 10, 20, 30, 40 }; Console.WriteLine(numbers[2]); // 30
stackalloc cria um buffer direto na stack - sem GC, sem alocacao no heap. Ideal para buffers pequenos e temporarios (<= poucos KB). O buffer e liberado automaticamente ao sair do escopo.
Como funciona stackalloc?
stackalloc reserva N bytes no stack frame do metodo atual. Nao passa pelo GC. O buffer e liberado quando o metodo retorna (stack pointer volta). Use para buffers pequenos e de curta duracao. Se o buffer for grande demais, causa StackOverflowException.