web-dev-qa-db-fra.com

En quoi le nouveau C # Span <T> est-il différent d’ArraySegment <T>?

J'ai du mal à conceptualiser les usages de la nouvelle portée en C #

  1. Quelles constructions remplace-t-il? ArraySegment est-il maintenant obsolète?

  2. Quelle fonctionnalité permet-il que ne l'était pas auparavant?

  3. Est-ce que Span est un remplacement valide pour les tableaux C #? Dans quels cas oui, dans quels cas non?

  4. Quand vais-je utiliser un ArraySegment au lieu d'une Span? 

J'essaie de comprendre comment mes styles de codage devront être modifiés pour utiliser efficacement la nouvelle Span.

18
TheFastCat

Span<T> ne remplace rien. C'est de la valeur ajoutée. Il fournit une vue de type sécurisé dans des segments de mémoire continus pouvant être alloués de différentes manières: sous forme de tableau géré, de mémoire sur pile ou de mémoire non gérée. 

ArraySegment<T> est limité aux matrices gérées. Vous ne pouvez pas l'utiliser pour encapsuler les données allouées sur la pile avec stackalloc. Span<T> vous permet de le faire.

ArraySegment<T> ne fournit pas non plus une vue en lecture seule dans le tableau sous-jacent. ReadOnlySpan<T> vous donne ça.

Span<T> n'est pas censé remplacer les tableaux. Au bout du compte, il ne s'agit que d'une vue dans les données. Ces données doivent être allouées d'une manière ou d'une autre et, dans le monde géré, cette allocation sera, dans la plupart des cas, une allocation de type tableau. Donc, vous avez encore besoin de tableaux.

Vous devriez utiliser Span<T> si vous voulez que votre code puisse manipuler plus que des tableaux. Par exemple. envisager une bibliothèque d'analyse. À l'heure actuelle, pour lui permettre de fonctionner avec des tableaux, une pile de mémoire allouée et une mémoire non gérée, il doit fournir plusieurs points d'entrée dans l'API pour chacun d'eux et utiliser un code non sécurisé pour manipuler les données. Il devrait également probablement exposer une API string-based à utiliser par les personnes dont les données sont allouées sous forme de chaînes. Avec Span et ReadOnlySpan, vous pouvez fusionner toute cette logique en une solution unique basée sur Span qui sera applicable dans tous ces scénarios.

Span<T> ne sera certainement pas utilisé par tout le monde et très souvent. Il s’agit d’une partie hautement spécialisée du framework .NET, utile principalement aux auteurs de bibliothèques et aux scénarios critiques à très hautes performances. Par exemple. Kestrel, le service Web derrière ASP.NET Core, tirera de nombreux avantages en termes de performances en passant à Span<T> car, par exemple, L'analyse de la demande peut être effectuée à l'aide de Span<T> et de la mémoire allouée par pile, ce qui n'exerce aucune pression sur GC. Mais vous, en écrivant des sites Web et des services basés sur ASP.NET Core, vous n'êtes pas obligé de l'utiliser.

20
MarcinJuraszek

From MSDN Magazine : Span est défini de telle sorte que les opérations puissent être aussi efficaces que sur les tableaux: l'indexation dans une étendue ne nécessite pas de calcul pour déterminer le début à partir d'un pointeur et son offset de départ, comme le champ ref elle-même encapsule déjà les deux. (En revanche, ArraySegment a un champ offset séparé, ce qui le rend plus coûteux à la fois pour l'indexation et le transfert.)

En outre, alors que Array implémente IEnumerable, Span ne le fait pas. 

4
Furkan Kambay

Tenez également compte de tout en décidant d’utiliser Span les limitations applicables à ref structs en C #:

https://docs.Microsoft.com/en-us/dotnet/api/system.span-1?view=netcore-2.2

Span est une structure ref qui est allouée sur la pile plutôt que sur le tas géré. Les types de structure Ref ont un certain nombre de restrictions à Assurez-vous qu'ils ne peuvent pas être promus dans le tas géré, y compris qu'ils ne peuvent pas être encadrés, ils ne peuvent pas être affectés à des variables de type Objet, dynamique ou à tout type d'interface, ils ne peuvent pas être des champs dans un type de référence, et ils ne peuvent pas être utilisés en attente et céder limites. En outre, les appels à deux méthodes, Equals (Object) et GetHashCode, lance une exception NotSupportedException.

Important

Du fait qu'il s'agisse d'un type de pile uniquement, Span ne convient pas à beaucoup scénarios qui nécessitent de stocker des références aux tampons sur le tas. Ce est vrai, par exemple, des routines qui font des appels de méthode asynchrone . Pour de tels scénarios, vous pouvez utiliser les logiciels complémentaires System.Memory et Types System.ReadOnlyMemory.

Pour les étendues représentant des structures immuables ou en lecture seule, utilisez System.ReadOnlySpan.

https://docs.Microsoft.com/en-us/dotnet/csharp/language-reference/keywords/ref?view=netcore-2.2#ref-struct-types

L'ajout du modificateur ref à une déclaration de structure définit ces instances de ce type doit être alloué par pile. En d'autres termes, les instances de ces types ne peuvent jamais être créés sur le tas en tant que membre d'un autre classe. La principale motivation de cette fonctionnalité était Span et les objets associés structures.

L'objectif de conserver un type de structure de référence en tant que variable allouée à la pile introduit plusieurs règles que le compilateur applique pour tous les ref struct les types.

  • Vous ne pouvez pas encadrer une structure de référence. 
  • Vous ne pouvez pas affecter un type de structure à une variable de type objet, dynamique ou à tout type d'interface.
  • Les types de structure ref ne peuvent pas implémenter d'interfaces.
  • Vous ne pouvez pas déclarer une structure de référence en tant que membre d'une classe ou d'une structure normale.
  • Vous ne pouvez pas déclarer des variables locales qui sont des types de structure de référence dans des méthodes asynchrones. Vous pouvez les déclarer dans des méthodes synchrones qui renvoient des types tâche, tâche ou type tâche.
  • Vous ne pouvez pas déclarer des variables de structure locales dans des itérateurs.
  • Vous ne pouvez pas capturer des variables de structure dans des expressions lambda ou des fonctions locales.
  • Ces restrictions garantissent que vous n'utilisez pas accidentellement une structure de référence d'une manière qui pourrait la promouvoir vers le tas géré.

Vous pouvez combiner des modificateurs pour déclarer une structure comme étant en lecture seule ref. UNE readonly ref struct combine les avantages et les restrictions de ref déclarations de struct et en lecture seule.

0
Vadim S.