Start Debugging
2026-06-20 Actualizado 2026-11-02 csharpdotnetperformancememory Edit on GitHub

¿Qué es Span<T> en C# y cuándo hace realmente más rápido tu código?

Span<T> puede evitar copias y asignaciones temporales al analizar o formatear memoria contigua. Conoce sus límites de vida útil y qué medir.

Este sitio utiliza a Walter, un agente de IA, para investigar, redactar y mantener el contenido. Proceso editorial y de verificación

Span<T> es una vista de longitud fija sobre memoria contigua: arrays, memoria de pila o memoria no administrada cuya duración se gestione correctamente. ReadOnlySpan<T> permite solo lectura mediante la vista. Los strings ofrecen ReadOnlySpan<char>, no un Span<char> modificable.

Crear la vista no crea ni transfiere la propiedad del almacenamiento. Eso no vuelve toda la operación libre de asignaciones ni garantiza que sea más rápida.

Corrección — 2 de noviembre de 2026: se retiraron tiempos sin verificar y una promesa universal de aceleración. Se corrigieron el tipo del literal UTF-8, los límites del retorno y las asignaciones. Los ejemplos se comprobaron con SDK 10.0.302 y C# 14, sin benchmark de rendimiento.

Evitar substrings temporales

Los parsers que aceptan spans pueden evitar strings intermedios. Este ejemplo analiza un formato exacto sin crear substrings para año, mes y día:

using System;
using System.Globalization;

string input = "2026-06-01";
DateOnly date = ParseIsoDate(input.AsSpan());
Console.WriteLine(date.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture));

static DateOnly ParseIsoDate(ReadOnlySpan<char> input) =>
    DateOnly.ParseExact(input, "yyyy-MM-dd", CultureInfo.InvariantCulture);

ParseExact valida la fecha y lanza una excepción ante datos inválidos. Usa TryParseExact si ese caso es esperado. Llamadas aisladas a int.Parse(input.Slice(...)) no validan por sí solas separadores ni fechas del calendario.

Usar un búfer temporal acotado

using System;
using System.Globalization;

Span<char> scratch = stackalloc char[32];
if (12345.TryFormat(scratch, out int written, provider: CultureInfo.InvariantCulture))
{
    ReadOnlySpan<char> formatted = scratch[..written];
    Console.Out.WriteLine(formatted); // 12345
    string owned = new string(formatted); // Allocates the resulting string.
    Console.WriteLine(owned);
}

ReadOnlySpan<byte> method = "GET"u8;
Console.WriteLine(method.SequenceEqual(new byte[] { 71, 69, 84 })); // True

El búfer evita un array temporal de caracteres. Crear el string final sigue asignando memoria. El array de bytes de la comparación también asigna memoria: muestra los valores, no un benchmark. "GET"u8 tiene tipo ReadOnlySpan<byte>.

Mantén stackalloc pequeño y acotado. Asignaciones grandes o repetidas dentro de bucles pueden agotar la pila. No uses un tamaño sin comprobar procedente de una petición; para datos mayores usa arrays o búferes de pool con gestión correcta.

Almacenamiento compartido y duración

Crear un segmento no copia elementos. Puede devolverse un span sobre un array si su almacenamiento sigue siendo válido; uno sobre un búfer local de pila no puede escapar del método. Se permiten campos Span en otro ref struct, no en clases o structs ordinarios. Desde C# 13 pueden existir variables ref-struct en métodos async mientras no crucen un await; para cruzarlo usa Memory<T>.

ReadOnlySpan<T> no congela el búfer. Mientras uses CollectionsMarshal.AsSpan(list), no agregues ni elimines elementos, aunque quede capacidad disponible.

Medir una mejora concreta

Busca una copia o asignación eliminable: substrings, segmentos copiados o arrays de formateo temporales. Un bucle normal sobre arrays o listas puede estar bien optimizado. La eliminación de comprobaciones y el rendimiento dependen del runtime y la carga; no existe un multiplicador fijo fiable.

Mide trabajo equivalente en Release con el runtime desplegado y datos representativos. Excluye la preparación, incluye asignaciones y conserva código y salida del benchmark. Este artículo no presenta nuevos tiempos medidos.

Las conversiones implícitas básicas de arrays a spans son anteriores a C# 14. C# 14 llegó con .NET 10 y amplió su integración en el lenguaje. allows ref struct, de C# 13, solo habilita APIs genéricas preparadas expresamente.

Para elegir el modelo de propiedad, consulta List, Span y ReadOnlySpan. Para almacenamiento async, ReadOnlyMemory desde un array.

Fuentes

Comments

Sign in with GitHub to comment. Reactions and replies thread back to the comments repo.