¿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 complementaSpan<T>
. Como se discutió en su documento de diseño,Span<T>
es un tipo de solo pila. La naturaleza de solo apilamiento deSpan<T>
hace inadecuado para muchos escenarios que requieren almacenar referencias a buffers (representados conSpan<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 deSpan <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 devuelveSpan<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 valorMemory<T>
. En cierto sentido, laMemory<T>
es una fábrica deSpan<T>
.
Documento de referencia: here