C # 7.2 introduit deux nouveaux types: Span<T>
et Memory<T>
qui offre de meilleures performances par rapport aux types C # précédents tels que string[]
.
Question: Quelle est la différence entre Span<T>
et Memory<T>
? Pourquoi devrais-je utiliser l'un sur l'autre?
Span<T>
est de type pile uniquement tandis que Memory<T>
peut exister sur le tas.
Span<T>
est un nouveau type que nous ajoutons à la plate-forme pour représenter des régions contiguës de mémoire arbitraire, avec des caractéristiques de performances égales à T []. Ses API sont similaires au tableau, mais contrairement aux tableaux, il peut pointer soit vers la mémoire gérée ou native, soit vers la mémoire allouée sur la pile.
Memory <T>
est un type complétantSpan<T>
. Comme indiqué dans son document de conception,Span<T>
est un type de pile uniquement. La nature de pile uniquement deSpan<T>
le rend impropre à de nombreux scénarios nécessitant de stocker des références dans des tampons (représentés parSpan<T>
) sur le tas, par exemple pour les routines faisant des appels asynchrones.
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;
}
Pour résoudre ce problème, nous allons fournir un ensemble de types complémentaires, destinés à être utilisés en tant que types d’échange à usage général représentant, tout comme
Span <T>
, une plage de mémoire arbitraire, mais contrairement àSpan <T>
ces types ne seront pas uniquement empilés, au prix de pertes de performances significatives pour la lecture et l’écriture en mémoire.
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;
}
Dans l'exemple ci-dessus, le
Memory <byte>
est utilisé pour représenter le tampon. C'est un type standard et peut être utilisé dans des méthodes faisant des appels asynchrones. Sa propriété Span renvoieSpan<byte>
, mais la valeur renvoyée n'est pas stockée sur le tas lors d'appels asynchrones, mais de nouvelles valeurs sont générées à partir duMemory<T>
valeur. Dans un sens,Memory<T>
est une usine deSpan<T>
.
Document de référence: ici
re: cela signifie qu'il ne peut pointer que vers la mémoire allouée sur la pile.
Span<T>
peut pointer sur n’importe quelle mémoire: allouée sur la pile ou sur le tas. Stack-only nature of Span<T>
signifie que le Span<T>
lui-même (pas la mémoire vers laquelle il pointe) doit résider uniquement sur la pile. Cela contraste avec les structures C # "normales", qui peuvent résider sur la pile ou sur le tas (soit via une box de type valeur, soit lorsqu'elles sont incorporées dans des classes/types de référence). Certaines des implications pratiques les plus évidentes sont que vous ne pouvez pas avoir un Span<T>
champ dans une classe, vous ne pouvez pas boxer Span<T>
, et vous ne pouvez pas en faire un tableau.