c# c#-7.2 system.memory

¿Cuál es la diferencia entre Span<T> y Memory<T> en C#7.2?



c#-7.2 system.memory (3)

C # 7.2 introduce dos nuevos tipos: Span<T> y Memory<T> que tienen un mejor rendimiento en comparación con los tipos anteriores de C # como string[] .

Pregunta: ¿Cuál es la diferencia entre Span<T> y Memory<T> ? ¿Por qué usaría uno sobre el otro?


re: esto significa que solo puede apuntar a la memoria asignada en la pila.

Span<T> puede apuntar a cualquier memoria: asignada en la pila o en el montón. La naturaleza de solo pila de Span<T> significa que la propia Span<T> (no la memoria a la que apunta) debe residir solo en la pila. Esto contrasta con las estructuras C # "normales", que pueden residir en la pila o en el montón (ya sea a través de un cuadro de tipo de valor o cuando están incrustados en clases / tipos de referencia). Algunas de las implicaciones prácticas más obvias son que no puede tener un campo Span<T> en una clase, no puede encuadrar Span<T> y no puede hacer una matriz de ellos.


Memory<T> puede verse como una versión insegura pero más versátil de Span<T> . El acceso a un objeto Memory<T> fallará si apunta a una matriz liberada.


Span<T> es solo de tipo stack mientras que Memory<T> puede existir en el montón.

Span<T> es un nuevo tipo que estamos agregando a la plataforma para representar regiones contiguas de memoria arbitraria, con características de rendimiento a la par con T []. Sus API son similares a la matriz, pero a diferencia de las matrices, puede apuntar a la memoria administrada o nativa, o a la memoria asignada en la pila.

Memory <T> es un tipo que complementa Span<T> . Como se discutió en su documento de diseño, Span<T> es un tipo de solo pila. La naturaleza de solo apilamiento de Span<T> hace inadecuado para muchos escenarios que requieren almacenar referencias a buffers (representados con Span<T> ) en el montón, por ejemplo, para rutinas que realizan llamadas asincrónicas.

async Task DoSomethingAsync(Span<byte> buffer) { buffer[0] = 0; await Something(); // Oops! The stack unwinds here, but the buffer below // cannot survive the continuation. buffer[0] = 1; }

Para abordar este problema, proporcionaremos un conjunto de tipos complementarios, destinados a ser utilizados como tipos de intercambio de propósito general que representan, al igual que Span <T> , un rango de memoria arbitraria, pero a diferencia de Span <T> estos tipos no serán apilados -solo, a costa de importantes penalizaciones de rendimiento por leer y escribir en la memoria.

async Task DoSomethingAsync(Memory<byte> buffer) { buffer.Span[0] = 0; await Something(); // The stack unwinds here, but it''s OK as Memory<T> is // just like any other type. buffer.Span[0] = 1; }

En el ejemplo anterior, la Memory <byte> se usa para representar el búfer. Es un tipo regular y puede usarse en métodos que realizan llamadas asincrónicas. Su propiedad Span devuelve Span<byte> , pero el valor devuelto no se almacena en el montón durante las llamadas asincrónicas, sino que se generan nuevos valores a partir del valor Memory<T> . En cierto sentido, la Memory<T> es una fábrica de Span<T> .

Documento de referencia: here