12
votes

Pourquoi avons-nous besoin de struct? (C #)

Pour utiliser une structure, nous devons instancier la structure et l'utiliser comme une classe. Alors pourquoi ne pouvons-nous pas simplement créer une classe en premier lieu?

c#

0 commentaires

9 Réponses :


1
votes

La différence est qu'une structure est un type de valeur Je les ai trouvés utile dans 2 situations

1) Interop - Vous pouvez spécifier la présentation de la mémoire d'une structure, vous pouvez donc garantir que lorsque vous appelez un appel non géré.

2) Performance - Dans certains cas (très limités), les structures peuvent être plus rapides que les classes, en général, cela nécessite des structures de petite taille (j'ai entendu 16 octets ou moins) et ne pas être changé souvent.


1 commentaires

Les structures de terrain exposées offrent leurs avantages de performance les plus importants dans les cas où la fréquence de deux opérations se situe dans quelques ordres de grandeur: (1) copier l'état encapsulé par une variable à une autre; (2) Modifier une partie de l'état encapsulé dans une variable. Les seules classes qui peuvent faire # 1 plus efficacement qu'une structure de toutes tailles sont des classes immuables et des classes immuables sont très mauvaises au n ° 2 (plus la classe la plus grande, la pire des performances). Dans les cas où les structures sont utilisables, ils surperlont des cours à moins que l'une de ces ops ne soit si rare que sa performance est un non-facteur,



18
votes

Une struct est une valeur de valeur, donc si vous créez une copie, elle copiera physiquement les données, alors qu'avec une classe, elle ne copiera que la référence aux données


6 commentaires

(Jusqu'à ce que vous intégriez un type de référence dans votre structure, quel événement ne copiera que la référence à cet objet)


Novatrust, ce n'est pas une exception à quelle adresse IP décrit.


La valeur d'un type de référence est la référence elle-même, ce qui doit être attendu. Je n'ai pas encore trouvé un bon moyen de décrire cela sans que cela sonne déroutant :(


Vrai, mais c'est une clarification valide. Les références d'emballage dans une structure ne créent pas comme par magie des copies profondes.


Pour vous et moi, mais pour que quelqu'un avec ait un faible compromis d'une valeur et des types de référence, c'est une distinction importante.


@novatrust: La déclaration de la propriété intellectuelle est correcte. La valeur d'un type de référence est la référence, pas le référent.



6
votes

en C #, une structure est un type de valeur, contrairement aux classes qui sont des types de référence. Cela conduit à une énorme différence dans la manière dont ils sont traités ou comment ils devraient être utilisés.

Vous devriez probablement lire des structures d'un livre. Les structures en C # ne sont pas des cousins ​​de classe de classe comme en C ++ ou Java.


0 commentaires

-1
votes

Une structure est un type de valeur (comme Int32), tandis qu'une classe est un type de référence. Les structures sont créées sur la pile plutôt que sur le tas. De plus, lorsqu'une structure est transmise à une méthode, une copie de la structure est passée, mais lorsqu'une instance de classe est passée, une référence est transmise.

Si vous devez créer votre propre type de données, disons, alors une structure est souvent un meilleur choix que d'une classe que vous pouvez l'utiliser, comme les types de valeur intégrés dans la structure .NET. Il existe de bons exemples de structure Vous pouvez lire ici .


16 commentaires

"Les structures sont créées sur la pile plutôt que le tas" Pas toujours - ne peragez pas cela, il est beaucoup de minerai subtil. Aussi, vous devriez dire une copie d'une référence est passée.


En outre, il s'agit simplement d'un détail de mise en œuvre.


Emmenez-le avec Microsoft, puis, car c'est ce que MSDN dit: "Lorsque vous appelez le nouvel opérateur d'une classe, il sera attribué sur le tas. Cependant, lorsque vous instaniez une structure, il est créé sur la pile." - msdn.microsoft.com/en-us/Library/ AA288471 (vs.71) .aspx


Novatrust: "En outre, il s'agit simplement d'un détail de mise en œuvre." Oui, c'est un détail de mise en œuvre, mais c'est un détail important dans certaines situations.


Les structures et autres types de valeur sont créés sur le tas tout le temps, à l'intérieur d'objets ou de tableaux.


Je vois que la police de Karma est en vigueur aujourd'hui.


@DAN: MSDN a prétendu que Decimal était un type de point fixe. Parfois, MSDN a tort. C'est dans ce cas.


Oui, mon patron a été émerveillé quand je lui ai dit à quel point la décimale a effectivement travaillé. De plus, le dernier JIT X86 peut entièrement enregistrer une structure ou une classe, qui n'est ni la pile ni le tas ... L'aspect important est la sémantique de la copie, pas l'emplacement en mémoire. Comme Nova stipule si correctement, "c'est la mise en œuvre" et non des spécifications. MSDN est tort trop souvent, quand c'est juste c'est génial.


@Jon - Nous ne sommes pas tous nés avec une connaissance intime du CLR par conséquent, nous comptons sur la documentation. Je suis heureux d'apprendre de nouvelles choses, mais les attitudes plutôt suffisantes et condescendantes ont exposé ici (on dit que je suis "perrocher", etc.) me fait me demander si je me suis déroulé à l'avenir.


@Dan: Avec tout le respect dû, cela pourrait être l'un de ces endroits où vous pourriez bien faire de la croissance d'une peau plus épaisse en ce qui concerne la critique constructive.


@Steven - Je n'ai aucun problème de critique constructive, juste impolitesse. La critique constructive est que vous avez souligné poliment pourquoi quelqu'un a tort, fournit une référence utile pour sauvegarder votre point et ne le faites pas de manière ouvertement élégante ni conteste. J'avais pensé que Stackoverflow était un peu plus simple que la plupart des forums à cet égard.


@Dan: Comme tout le reste, il varie. Certaines critiques sont des politres que d'autres, et la tolérance de la volonté des personnes varie également, il y a donc de quelques plumes à volants tôt ou tard. C'est pourquoi je préfère me concentrer sur le contenu plutôt que le ton. Ce qui rend la critique constructive n'est pas de savoir si c'est poli, mais plutôt si cela aide. Dans ce cas, vous avez été évité parce que vous avez répété une idée fausse commune. Je ne t'aurais pas révélé, moi-même. En fait, je viens de susciter de manière stratégique. Cependant, votre réponse était incorrecte, il est donc bon qu'il ait été rejeté.


@Dan Commentaire Textboxes Sont petits - j'ai tendance à atteindre le point avec cela, car il s'agit d'une erreur d'une OFT. Les structures peuvent être créées de loin que de nouvelles. Si vous allez dire mettre votre point de vue là-bas, l'ONUS est sur vous pour vous assurer que vous avez raison, vous attendez à vous dire quand vous avez tort (nous sommes tous à un moment donné) en apprennent et devenez mieux. Si vous répétez ce que vous avez lu / entendez sans la comprendre ou la critiquer, vous perrojetez, désolé si cela offense, mais c'est vrai.


En train de côté, je n'ai pas réellement été votre question, bien que si vous aimez que je puisse puis que votre Supprimer vous obtiendrait un badge de pression par des pairs.


Merci pour vos commentaires - je comprends et respectez ce que vous dites. Je ne suis pas du tout dérangé pour les points ou être voté. Mais ... cela ne prend pas beaucoup plus d'efforts pour corriger quelqu'un de manière polie qu'en dérisoire. Je pense aussi qu'il est utile de dire plus que: "Vous avez tort" - fournir une explication ou un lien vers cette opération (surtout lors de la création de revendications que MSDN est incorrecte!) Pour que les gens puissent apprendre et comprendre pourquoi / I> C'est faux. Ainsi, de tels nouveaux membres ne sont pas entièrement déduits contribuant à l'avenir et les gens peuvent véritablement apprendre de leurs erreurs.


Si vous voulez un lien décent sur la raison pour laquelle Jon Skeet's Article est en profondeur, mais est très intéressant: Yoda .Arachsys.com / Csharp / Memory.html



1
votes

L'une des principales raisons est que, lorsqu'il est utilisé comme variables locales pendant un appel de méthode, les structures sont allouées sur la pile.

L'allocation de pile est bon marché, mais la grande différence est que Désaislocation est également très bon marché. Dans cette situation, le collecteur des ordures ne doit pas nécessairement suivre les structures - ils sont retirés lors du retour de la méthode qui les a attribués lorsque le cadre de pile est sauté.

  • Edit - clarifié My Post Re: Le commentaire de Jon Skeet.

6 commentaires

Les structures sont allouées "en ligne" avec la variable. Que peut sur la pile, ou peut-être sur le tas s'il fait partie d'un autre objet.


C'est vrai, je venais du point de vue des variables locales :) (par exemple, effectuer un calcul dans une méthode utilisant plusieurs variables locales). J'aurais dû clarifier cela.


Cela fait référence aux détails de la mise en œuvre et non à des différences sémantiques entre "classe" et "struct".


La question qu'il a posée est "pourquoi avons-nous besoin de structure?". Ma réponse contient une optique valide et pratique - des structures moins chères sont moins chères pour désaffecter par rapport aux classes que le GC n'a pas à les suivre. Lors de l'écriture d'un type simple qui sera instancié des milliers de fois dans une courte période de temps, vous vous souciez probablement de cette différence. Dans certains cas, les détails de la mise en œuvre.


Premièrement, rien ne garantit que les structures seront désormais allouées sur la pile; Cela ne fait pas partie de la spécification de la langue. La gigue peut allouer la structure partout où elle plaira tant qu'elle observe la sémantique de la valeur des structures. Deuxièmement, nous avons besoin de structures de la différence de performance (comme actuellement mise en œuvre), mais pour la sémantique de la valeur qu'ils fournissent. Troisièmement, le choix de l'utilisation des structures par rapport aux classes ne doit être faite que après le profilage. La plupart du temps, le choix doit être fait sur la base de savoir si nous voulons une sémantique de la valeur de la sémantique de référence.


1. Je doute sérieusement que cela va changer. 2. C'est une raison pour laquelle les structures sont nécessaires; Ce n'est pas la seule raison. 3. Je suis d'accord. Nous venons effectivement avoir une situation au travail où nous avons profilé et que nous avons constaté qu'il était logique de remplacer diverses classes avec des structures.



1
votes

Les structures ont de nombreuses sémantiques différentes aux classes. Les différences sont nombreuses mais les principales raisons de leur existence sont les suivantes:

  1. ils peuvent être explicitement exposés dans des mémoires
    • Cela permet certains scénarios interopers
    • Ils peuvent être alloués sur la pile
      • Faire des sortes de code de haute performance possibles de manière beaucoup plus simple

0 commentaires

7
votes

Toutes les raisons que je vois dans d'autres réponses sont intéressantes et peuvent être utiles, mais si vous voulez savoir pourquoi ils sont nécessaires (au moins par la machine virtuelle) et pourquoi c'était un < EM> Errument pour le JVM ne les prend pas en charge (types de valeur définis par l'utilisateur), lisez Magie de démystification: programmation de haut niveau . Comme il se trouve, c # brille de parler du potentiel d'apporter un code géré sûr de la programmation des systèmes. C'est également l'une des raisons pour lesquelles je pense que la CLI est une plate-forme supérieure [que la JVM] pour l'informatique mobile. Quelques autres raisons sont énumérées dans le papier lié.

Il est important de noter que vous allez très rarement, si jamais, voir une amélioration de la performance observable de l'utilisation d'une structure. Le collecteur des ordures est extrêmement rapide et dans de nombreux cas surperformera les structures. Lorsque vous ajoutez dans les nuances d'eux, ils ne sont certainement pas un outil de premier choix. Cependant, lorsque vous en avez besoin et que vous avez des résultats de profileur ou des constructions de niveau système pour le prouver, ils obtiennent le travail.

Edit: Si vous vouliez une réponse de la raison pour laquelle nous en avons besoin, par opposition à ce qu'ils font, ^^^


3 commentaires

Les structures à blitter d'un tampon non gérée sont géniales pour la performance :)


Certaines types de choses sont décrites comme un ensemble fixe de valeurs indépendantes; Les opérations sur eux se concentreront sur deux opérations de base: définir une propriété d'un emplacement de stockage égale à une certaine valeur ou faire correspondre toutes les propriétés d'un emplacement correspondant à ceux d'un autre. Les classes mutables non partagées sont bonnes au premier, mais mauvais au second. Les classes immuables sharables sont mauvaises au premier, mais excellentes à la seconde. Les structures de terrain exposées sont excellentes pour le premier et décent à la seconde. Les soi-disant structures immuables sont mauvaises au premier et décent à la seconde.


Plutôt que de dire "on voit rarement une amélioration de la performance de l'utilisation d'une structure", il serait utile de savoir quels types de structures sont comparées à quels types de classes et quel est le modèle d'utilisation. Notez également que dans les scénarios où aucune des deux opérations susmentionnées ne domine, les avantages de la performance des structures augmentent avec la taille jusqu'à ce qu'ils deviennent si gros de souffler la pile. Ce n'est que lorsque la deuxième opération domine que les grands objets de classe surperforment sensiblement de grandes structures.



8
votes

Une différence majeure entre la sémantique de la classe et struct est que struct s ont une sémantique de valeur. Ce que cela signifie que si vous avez deux variables du même type, elles ont chacune leur propre copie des données. Ainsi, si une variable d'un type de valeur donné est réglée égale à une autre (du même type), les opérations sur une autre n'affectent pas l'autre (c'est-à-dire que l'attribution des types de valeur crée une copie). Cela contraste fortement avec les types de référence.

Il existe d'autres différences:

  1. Les types de valeur sont implicitement scellés (il n'est pas possible de dériver d'une valeur de valeur).
  2. Types de valeur ne peut pas être null .
  3. Les types de valeur sont donnés un constructeur par défaut qui initialze le type de valeur à sa valeur par défaut.
  4. Une variable d'un type de valeur est toujours une valeur de ce type. Contrôlez cela avec des classes où une variable de type A pourrait se référer à une instance de type B si b dérive de a .

    En raison de la différence de sémantique, il est inapproprié de se référer à struct s comme "classes légères".


2 commentaires

"Deux variables du même type, ils ont chacun leur propre copie des données" ... N'est-ce pas la même chose que Var X = Nouvelle Soméclass () et Var Y = Nouveau Soméclass ()? Ils auraient tous deux leur propre copie des données.


@Vince: regardez-le comme ça. Si vous avez var x = nouveau soméclass (); et var y = x; puis mutation x muté y . Mais si vous avez var x = nouveau surstruct (); et var y = x; Ce n'est pas le cas.



3
votes

Ceci est un mythe que les struct sont toujours créées sur le tas. OK, il est correct que la structure est le type de valeur et la classe est un type de référence. Mais rappelez-vous que

1. Un type de référence va toujours sur le tas.
2. Les types de valeur vont où ils ont été déclarés. Strong> P>

Maintenant que ce moyen de deuxième ligne est que je vais expliquer avec l'exemple ci-dessous P>

Considérez la méthode suivante P> XXX PRE>

ICI Num est une variable locale, elle sera donc créée sur Stack Strong>. P>

Prenez maintenant l'exemple ci-dessous P>

public class TestClass
{          
    public int num;
}
public void DoCalulation()
{
    TestClass myTestClass = new TestClass ();
    myTestClass.num=2;
}


0 commentaires