Translate

lunes, 5 de mayo de 2025

Span en C#: Acceso seguro y eficiente a la memoria


A partir de C# 7.2 y .NET Core 2.1, Microsoft introdujo una de las herramientas más poderosas para manipular memoria sin sacrificar seguridad: Span<T>. Esta estructura permite trabajar con porciones contiguas de memoria (arrays, segmentos de strings, buffers, etc.) de forma eficiente, sin generar asignaciones en el heap ni usar punteros directamente.

Span<T> es una estructura stack-only que representa una ventana mutable sobre un bloque contiguo de memoria. Podés usarlo para acceder, cortar o modificar datos de arrays, slices de strings, buffers nativos, y más, sin necesidad de copiar datos.

Veamos un ejemplo: 


int[] numbers = { 1, 2, 3, 4, 5 };

Span<int> slice = numbers.AsSpan(1, 3); // Contiene 2, 3, 4


slice[0] = 42;

Console.WriteLine(numbers[1]); // Muestra 42 (modificó el array original)


¿Por qué usar Span<T>?

  • Evita copias de memoria innecesarias
  • No genera asignaciones en el heap 
  • Mejora la performance en procesamiento de strings, buffers y arrays  
  • Ofrece seguridad de tipos y bounds-checking
  • Solo puede usarse dentro del stack (no puede almacenarse en campos de clase)


Limitaciones:

  • No puede usarse en métodos async o iteradores (async, yield return)  
  • No puede almacenarse en campos de clase o como parte de objetos del heap
  • Si necesitás algo similar pero heap-safe, podés usar Memory<T>


Veamos un ejemplo de string: 


ReadOnlySpan<char> span = "Hola Mundo".AsSpan(5);

Console.WriteLine(span.ToString()); // Mundo


Esto es ideal para parsear strings sin crear substrings intermedias.

Span<T> es una herramienta fundamental si querés escribir código de alto rendimiento en .NET. Es ideal para manipular datos binarios, strings o buffers, con el mínimo impacto en el garbage collector. Aunque tiene limitaciones (no se puede escapar del stack), su potencia compensa con creces en escenarios críticos de performance.