MSDN dit que vous devez utiliser des structures lorsque vous avez besoin d'objets légers. Y a-t-il d'autres scénarios où une structure est préférable à une classe?
Certaines personnes ont peut-être oublié que:
- les structures peuvent avoir des méthodes.
- les structures ne peuvent pas être héritées.
Je comprends les différences techniques entre les structures et les classes, je ne sais tout simplement pas quand utiliser une structure.
Réponses:
MSDN a la réponse: choisir entre les classes et les structures .
Fondamentalement, cette page vous donne une liste de contrôle en 4 points et dit d'utiliser une classe à moins que votre type ne réponde à tous les critères.
la source
ref
paramètres chaque fois qu'il est raisonnable de le faire. Passer une structure avec 4 000 champs comme paramètre ref à une méthode qui en change une sera moins cher que de passer une structure avec 4 champs par valeur à une méthode qui retourne une version modifiée.Je suis surpris de n'avoir lu aucune des réponses précédentes, que je considère comme l'aspect le plus crucial:
J'utilise des structures lorsque je veux un type sans identité. Par exemple un point 3D:
Si vous avez deux instances de cette structure, vous ne vous souciez pas s'il s'agit d'une seule donnée en mémoire ou de deux. Vous vous souciez juste de la valeur (s) qu'ils détiennent.
la source
return false
est ce qui aurait dû être là, corrigeant maintenant.Bill Wagner a un chapitre à ce sujet dans son livre "effective c #" ( http://www.amazon.com/Effective-Specific-Ways-Improve-Your/dp/0321245660 ). Il conclut en utilisant le principe suivant:
la source
Utilisez une structure lorsque vous voulez une sémantique de type valeur au lieu de type référence. Les structures sont copiées par valeur, alors faites attention!
Voir également les questions précédentes, par exemple
Quelle est la différence entre struct et class dans .NET?
la source
J'utiliserais des structures lorsque:
un objet est censé être en lecture seule (chaque fois que vous passez / assignez une structure, il est copié). Les objets en lecture seule sont parfaits en matière de traitement multithread car ils ne nécessitent pas de verrouillage dans la plupart des cas.
un objet est petit et de courte durée. Dans un tel cas, il y a de fortes chances que l'objet soit alloué sur la pile, ce qui est beaucoup plus efficace que de le placer sur le tas managé. De plus la mémoire allouée par l'objet sera libérée dès qu'elle sortira de sa portée. En d'autres termes, c'est moins de travail pour Garbage Collector et la mémoire est utilisée plus efficacement.
la source
Utilisez une classe si:
Utilisez une structure si:
la source
J'ai toujours utilisé une structure lorsque je voulais regrouper quelques valeurs pour renvoyer des choses à partir d'un appel de méthode, mais je n'aurai pas besoin de l'utiliser pour quoi que ce soit après avoir lu ces valeurs. Tout comme un moyen de garder les choses propres. J'ai tendance à voir les choses dans une structure comme "jetables" et les choses dans une classe comme plus utiles et "fonctionnelles"
la source
Si une entité doit être immuable, la question de l'utilisation d'une structure ou d'une classe sera généralement une question de performance plutôt que de sémantique. Sur un système 32/64 bits, les références de classe nécessitent 4/8 octets à stocker, quelle que soit la quantité d'informations dans la classe; la copie d'une référence de classe nécessite la copie de 4/8 octets. D'autre part, tous distinctsl'instance de classe aura 8/16 octets de surcharge en plus des informations qu'elle contient et du coût de la mémoire des références. Supposons que l'on veuille un tableau de 500 entités, chacune contenant quatre entiers 32 bits. Si l'entité est un type de structure, le tableau nécessite 8 000 octets, que les 500 entités soient toutes identiques, toutes différentes ou quelque part entre les deux. Si l'entité est un type de classe, le tableau de 500 références prendra 4 000 octets. Si ces références pointent toutes vers des objets différents, les objets nécessiteraient 24 octets supplémentaires chacun (12 000 octets pour les 500), soit un total de 16 000 octets, soit le double du coût de stockage d'un type struct. D'un autre côté, du code a créé une instance d'objet, puis copié une référence aux 500 emplacements de tableau, le coût total serait de 24 octets pour cette instance et 4, 000 pour la baie - un total de 4 024 octets. Une économie importante. Peu de situations fonctionneraient aussi bien que la dernière, mais dans certains cas, il peut être possible de copier certaines références dans suffisamment d'emplacements de tableau pour que ce partage en vaille la peine.
Si l'entité est censée être mutable, la question de savoir s'il faut utiliser une classe ou une structure est à certains égards plus facile. Supposons que "Thing" soit une structure ou une classe qui a un champ entier appelé x, et on fait le code suivant:
Veut-on que cette dernière instruction affecte t1.x?
Si Thing est un type de classe, t1 et t2 seront équivalents, ce qui signifie que t1.x et t2.x seront également équivalents. Ainsi, la deuxième instruction affectera t1.x. Si Thing est un type de structure, t1 et t2 seront des instances différentes, ce qui signifie que t1.x et t2.x feront référence à des entiers différents. Ainsi, la deuxième instruction n'affectera pas t1.x.
Les structures mutables et les classes mutables ont des comportements fondamentalement différents, bien que .net ait quelques bizarreries dans sa gestion des mutations struct. Si l'on veut un comportement de type valeur (ce qui signifie que "t2 = t1" copiera les données de t1 vers t2 tout en laissant t1 et t2 comme des instances distinctes), et si l'on peut vivre avec les caprices de la gestion des types de valeur par .net, utilisez une structure. Si l'on veut une sémantique de type valeur mais que les caprices de .net entraîneraient une sémantique de type valeur cassée dans son application, utilisez une classe et marmonnez.
la source
De plus, les excellentes réponses ci-dessus:
Les structures sont des types de valeur.
Ils ne peuvent jamais être définis sur Nothing .
Définir une structure = Rien, mettra tous ses types de valeurs à leurs valeurs par défaut.
la source
lorsque vous n'avez pas vraiment besoin de comportement, mais que vous avez besoin de plus de structure qu'un simple tableau ou dictionnaire.
Suivi Voici comment je pense aux structures en général. Je sais qu'ils peuvent avoir des méthodes, mais j'aime garder cette distinction mentale globale.
la source
Comme l'a dit @Simon, les structures fournissent une sémantique de "type valeur", donc si vous avez besoin d'un comportement similaire à un type de données intégré, utilisez une structure. Puisque les structures sont passées par copie, vous voulez vous assurer qu'elles sont de petite taille, environ 16 octets.
la source
C'est un sujet ancien, mais je voulais fournir un test de référence simple.
J'ai créé deux fichiers .cs:
et
Exécuter le benchmark:
Résultats:
la source
Hmm ...
Je n'utiliserais pas la récupération de place comme argument pour / contre l'utilisation de structures vs classes. Le tas géré fonctionne un peu comme une pile - la création d'un objet le place simplement en haut du tas, ce qui est presque aussi rapide que l'allocation sur la pile. De plus, si un objet est de courte durée et ne survit pas à un cycle de GC, la désallocation est gratuite car le GC ne fonctionne qu'avec de la mémoire qui est toujours accessible. (Recherchez MSDN, il y a une série d'articles sur la gestion de la mémoire .NET, je suis juste trop paresseux pour aller les chercher).
La plupart du temps, j'utilise une structure, je finis par me donner des coups de pied parce que je découvre plus tard qu'avoir une sémantique de référence aurait rendu les choses un peu plus simples.
Quoi qu'il en soit, ces quatre points dans l'article MSDN publié ci-dessus semblent être une bonne ligne directrice.
la source
class MutableHolder<T> { public T Value; MutableHolder(T value) {Value = value;} }
, puis aMutableHolder<T>
sera un objet avec une sémantique de classe mutable (cela fonctionne aussi bien s'ilT
s'agit d'une structure ou d'un type de classe immuable).Les structures sont sur la pile et non sur le tas, donc elles sont thread-safe et doivent être utilisées lors de l'implémentation du modèle d'objet de transfert, vous ne voulez jamais utiliser d'objets sur le tas, elles sont volatiles, vous voulez dans ce cas utiliser la pile d'appels, ceci est un cas de base pour utiliser une structure, je suis surpris par toutes les réponses ici,
la source
Je pense que la meilleure réponse est simplement d'utiliser struct quand ce dont vous avez besoin est une collection de propriétés, classe quand c'est une collection de propriétés ET de comportements.
la source