43 votes

Pourquoi cela est-il implémenté en tant que structure?

Dans System.Data.Linq, EntitySet<T> utilise quelques structures ItemList<T> qui ressemblent à ceci:

  internal struct ItemList<T> where T : class
  {
    private T[] items;
    private int count;
    ...(methods)...
  }
 

(Il m'a fallu plus de temps que prévu pour découvrir ceci. Je ne comprenais pas pourquoi le champ Entités dans EntitySet<T> ne lançait pas d'exceptions de référence nulles!)

Ma question est la suivante: quels sont les avantages de l’implémentation de ceci en tant que structure sur une classe?

34voto

Martin Liversage Points 43712

Supposons que vous souhaitez stocker ItemList<T> dans un tableau.

L'allocation d'un tableau de types de valeur (struct) va stocker les données à l'intérieur de la matrice. Si, en revanche, ItemList<T> a été un type de référence (class), seules les références à ItemList<T> objets seront stockés à l'intérieur du tableau. Le actualy ItemList<T> objets seraient alloués sur le tas. Un niveau supplémentaire d'indirection est nécessaire pour atteindre une ItemList<T> de l'instance et que c'est tout simplement un tableau combinés avec une longueur, il est plus efficace d'utiliser un type de valeur.

Struct vs class

Après l'inspection du code de EntitySet<T> je peux voir qu'aucun tableau n'est impliqué. Cependant, une EntitySet<T> contient encore deux ItemList<T> des cas. En tant que ItemList<T> est struct le stockage de ces instances sont répartis à l'intérieur de l' EntitySet<T> objet. Si un class a été utilisé à la place de l' EntitySet<T> aurait contenu les références pointant vers EntitySet<T> objets attribués séparément.

La différence de rendement entre l'utilisation de l'un ou l'autre peut ne pas être perceptible dans la plupart des cas, mais peut-être que le développeur a décidé qu'il voulait traiter de la matrice et de la étroitement associée comptent comme une seule valeur, simplement parce qu'il semblait la meilleure chose à faire.

9voto

Rick Sladkey Points 23389

Pour la petite critique interne des structures de données comme ItemList<T>, nous avons souvent le choix d'utiliser un type de référence ou une valeur de type. Si le code est bien écrit, passant de l'un à l'autre est d'un banal changement.

Nous pouvons spéculer que d'un type de valeur évite des tas d'allocation et d'un type de référence évite struct copie de sorte qu'il n'est pas immédiatement clair de toute façon, car elle dépend de tellement de choses sur la façon dont il est utilisé.

La meilleure façon de trouver celui qui est le mieux est de le mesurer. Selon ce qui est le plus rapide est le gagnant clair. Je suis sûr qu'ils ont fait de leur analyse comparative et struct a été plus rapide. Après vous avez fait cela à quelques reprises, votre intuition est assez bon et le test confirme que votre choix était le bon.

6voto

Reniuz Points 5951

Peut-être que c'est important que ... citation à propos de struct d' ici

La nouvelle variable et la variable d'origine contiennent donc deux copies distinctes des mêmes données. Les modifications apportées à une copie n'affectent pas l'autre copie .

Juste penser, ne me jugez pas dur :)

5voto

Guffa Points 308133

Il n'y a que deux raisons à utiliser une structure, et qui est d'obtenir soit le type de valeur sémantique, ou pour de meilleures performances.

Comme la structure contient un tableau, le type de la valeur sémantique ne fonctionne pas bien. Lorsque vous copiez la structure que vous obtenez une copie de l' count, mais vous n'obtiendrez qu'une copie de la référence au tableau, pas une copie des éléments dans le tableau. Par conséquent, vous devez prendre des précautions particulières lorsque la structure est copié de sorte que vous n'obtenez pas incompatible instances de celui-ci.

Donc, la seule raison valable serait de performance. Il y a une petite surcharge pour chaque type de référence de l'instance, donc si vous avez beaucoup d'entre eux il peut y avoir un gain de performance notable.

Une fonctionnalité utile d'une telle structure, c'est que vous pouvez créer un tableau d'entre eux, et vous obtenez un tableau vide des listes sans avoir à initialiser chaque liste:

ItemList<string>[] = new ItemList<string>[42];

Comme les éléments du tableau sont de zéro-rempli, l' count membre sera égal à zéro et l' items membre sera nulle.

2voto

Tony the Pony Points 13235

Pures spéculations ici:

Étant donné que l’objet est assez petit (n’a que deux variables de membre), il est judicieux de le transformer en struct afin de lui permettre de le transmettre en tant que ValueType .

De plus, comme le souligne @Martin Liversage, en tant que ValueType il peut être stocké plus efficacement dans des structures de données plus grandes (par exemple, en tant qu’élément dans un tableau), sans la surcharge d’un objet individuel et d’une référence. à cela.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X