web-dev-qa-db-fra.com

Quelle est la différence entre Span <T> et Memory <T> en C # 7.2?

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?

51
Dan Sorensen

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étant Span<T>. Comme indiqué dans son document de conception, Span<T> est un type de pile uniquement. La nature de pile uniquement de Span<T> le rend impropre à de nombreux scénarios nécessitant de stocker des références dans des tampons (représentés par Span<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 renvoie Span<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 du Memory<T> valeur. Dans un sens, Memory<T> est une usine de Span<T>.

Document de référence: ici

49
Hussein Salman

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.

27
Krzysztof Cwalina