Struct et IDisposable
Je me demande pourquoi n'est-il pas compiler?
public static void Main(string[] args)
{
using (MyStruct sss = new MyStruct())
{
sss.s = "fsdfd";//Cannot modify members of 'sss' because it is a 'using variable'
//sss.Set(12); //but it's ok
}
}
public struct MyStruct : IDisposable
{
public int n;
public string s;
public void Set(int n)
{
this.n = n;
}
public void Dispose()
{
Console.WriteLine("dispose");
}
}
Mise à JOUR:
Mais il fonctionne parfaitement. Pourquoi?
public static void Main(string[] args)
{
using (MyClass sss = new MyClass())
{
sss.Field = "fsdfd";
}
}
public class MyClass:IDisposable {
public string Property1 { get; set; }
public string Field;
public void Method1 (){}
public void Dispose()
{
Console.WriteLine("dispose class");
}
}
Je vais tirer sur les gens si je l'ai jamais vu quelqu'un la mise en œuvre de
sera-ce des gens au hasard ou à la personne de la mettre en œuvre? Pourrait être bon à savoir.
Vous devez expliquer pourquoi 🙂 Et je n'ai toujours pas voir l'explication sur la raison de cette. Pourquoi la classe(es), c'est différent?
Au passage, vous ne pouvez pas le faire même lorsque vous utilisez un
Voir Daniel Earwicker de réponse.
IDisposable
sur un struct
.sera-ce des gens au hasard ou à la personne de la mettre en œuvre? Pourrait être bon à savoir.
Vous devez expliquer pourquoi 🙂 Et je n'ai toujours pas voir l'explication sur la raison de cette. Pourquoi la classe(es), c'est différent?
Au passage, vous ne pouvez pas le faire même lorsque vous utilisez un
foreach (var sss in new List<MyStruct>())
Voir Daniel Earwicker de réponse.
OriginalL'auteur Alexandre | 2011-10-27
Vous devez vous connecter pour publier un commentaire.
La classe et de la structure des scénarios sont en fait les mêmes, mais vous voyez des effets différents.
Lorsque vous modifiez la classe exemple :
Vous obtiendrez la même erreur sur la première cession.
L'explication est: Vous ne pouvez pas modifier (muter) à l'aide de la variable. Mais pour une catégorie qui s'applique à la référence, et non à l'instance.
Et la leçon est la suivante: Ne pas utiliser des structures. Et surtout ne pas utiliser les structures mutables.
quelque chose qui est "mutable" est quelque chose qui peut changer (muter). Une structure qui peut changer sa valeur est appelée mutable struct, et est généralement considéré comme quelque chose de mauvais. En savoir plus: Pourquoi mutable structs mal?
OriginalL'auteur Henk Holterman
Un certain nombre de personnes liées à mon article sur la mutation des types de valeur et pourquoi c'est une mauvaise idée. S'il est important de comprendre ces concepts pour comprendre pourquoi son une mauvaise idée de disposer d'une structure, et une moins bonne idée de la mutation de l'struct lorsque vous le faites, qui n'est effectivement pas le bon article pour le lien. Celui que vous voulez lire qui explique tout cela dans les plus petits détails:
http://ericlippert.com/2011/03/14/to-box-or-not-to-box/
En bref: "l'aide" de fait une copie du type de valeur, et vous êtes par conséquent, l'élimination une copie. Cela signifie que vous devez être très prudent-si la valeur est, disons, un système d'exploitation de la poignée, il pourrait y avoir beaucoup d'exemplaires de la valeur située autour de la mémoire, et vous aurez besoin pour vous assurer que vous disposer exactement une fois, peu importe combien d'exemplaires il y a des.
Voir aussi Si mon struct implémente IDisposable, il sera boxed lorsqu'utilisé dans une instruction d'utilisation?
(Dictionnaire a été choisi comme l'arbitraire d'un type de classe, je sais que c'est pas le meilleur pour cet exemple). Si someStructType dispose d'un champ int I, et StructArr est un tableau de someStructType, quels seront les effets de "StructArr[3].I+=4;" sur StructArr[4].J' ? Si someClassType dispose d'un champ int I, et ClassArr est un tableau de someClassType, quels seront les effets de "ClassArr[3].I+=4;" sur ClassArr[4].J'? Les Classes ont certainement leur place, mais si un type est utilisé pour représenter les valeurs, et si la mutabilité serait utile, puis une mutable type de valeur est souvent plus approprié qu'une mutable type de classe.
J'ai commenté le post que vous avez lié mais en bref: tout ce que vous soutenez peut être fait avec immuables types de valeur. Pourquoi devraient-ils être spécifiquement mutable?
Warholic: Avec une entité immuable, on doit réécrire tous les domaines si l'on veut changer l'un d'eux. Si ce que l'on veut faire, c'est modifier un champ d'une structure (struct), je vous conseille de le faire est à la fois plus claire et plus performant que la création d'une nouvelle structure dans laquelle presque tous les champs ont des valeurs qui correspondent à celles de la première. Quel avantage par une réécriture de tout pour faire un changement?
Exactement comment est la mutation d'un type de valeur de claire quand il est trivial de donner des exemples où la mutation d'un type de valeur produit des résultats incorrects? La raison pour laquelle les gens font valoir pour l'immuabilité sur les types de valeur est précisément parce que la perte de performance (le cas échéant) vaut bien la capacité de raisonner sur le code de manière efficace. Pour le absolue la plus critique pour les performances des zones mutables types de valeur peut être utile (pour les sommets dans un modèle 3D); mais ces types de situations sont peu et loin entre.
OriginalL'auteur Eric Lippert
L'idée d'un
using
déclaration est de veiller à ce qu'une ressource est rendue lorsque vous quittez le bloc.Lorsque vous affecter à une variable struct, vous êtes effectivement le remplacer par un tout nouvel objet de ce type. Donc, dans ce contexte, vous avez de s'en débarrasser de l'objet qui est censé avoir été va être éliminés.
Sont struct copie sur écriture en C# lors de l'utilisation de champs/propriétés?
Non, mais l'utilisation de foreach) des constructions créer une variable temporaire. Les Classes sont de bons car ce n'est qu'une référence.
pas de. Envisagez-vous de la façon dont les chaînes sont parfois d'oeuvre en C++? Les structures sont juste mutable objets qui sont la propriété exclusive de la variable qui se rapporte à eux. La variable peut être immuables (comme dans ce cas), et l'auteur de la struct peut marquer des champs de l'individu au sein de la structure comme immuable (via le
readonly
mot-clé).Et en fait, la (vraie) question est/doit être "pourquoi la variable est immuable" pas "pourquoi je ne peux pas utiliser les champs". Et il est intéressant de noter que vous ne pouvez pas utiliser les même propriétés (en considérant qu'une propriété n'a pas vraiment BESOIN de modifier un champ).
OriginalL'auteur Daniel Earwicker
De considérer les éléments suivants:
Maintenant faire:
Cette affiche:
Exactement. Il montre comment le faire, si tu le voulais vraiment ;P
Puis l'écrire! Le fait que la conversion à une interface d'un type de valeur causes de boxe (à l'extérieur du générique-avec-contrainte cas) n'est pas évident pour 75% de la C#, programmeurs 🙂
Je n'ai vraiment pas envie pour l'encourager 🙂 Il est acceptable que si le programmeur sait ce qu'il/elle est en train de faire exactement.
OriginalL'auteur leppie
Enfin, j'ai compris 🙂 je vais poster mon avis 🙂 🙂
Maintenant...
est méta-équivalent à
avec
readonly
ayant le même sens de lareadonly
mot clé class/struct déclaration.Si
MyType
est une référence, c'est la référence (et non pas de l'objet référencé) qui est "protégé". Si vous ne pouvez pas faire:mais vous pouvez
à l'aide du bloc.
Si
MyType
est un type de valeur de lareadonly
"modificateur" s'étend à ses champs/propriétés. Donc ils n'ont pas introduit un nouveau type de "const-ness/readonly-ness" dansusing
, ils ont simplement utilisé celui qu'ils avaient.De sorte que la question devrait être: pourquoi ne puis-je pas modifier les champs/propriétés de
readonly
types de valeur?Notez que si vous faites cela:
Résultat
de sorte que le
using
est en train de faire une copie "privé" desss
, etsss.n = 12
accède à "l'original"sss
, tandis queDispose
est l'accès à la copie.Je dois dire la vérité, le fait que les champs et les propriétés de la valeur en lecture seule les types sont en lecture seule n'est pas quelque chose de "évident" Il n'y a pas de réelles évident pour cette raison (en considérant que le type de valeur est toujours mutable par des méthodes, et que les propriétés sont de plus en plus semblables à des méthodes que pour les champs). Et le fait que les deux "lire-onlyness" sont les mêmes n'est pas évident non plus.
readonly n'a rien à voir avec cela. C'est de la sémantique des structures vs classes. le premier est, en valeur, cette dernière est par référence. Si vous "référence" de l'ancien, une copie de la valeur, le dernier une copie de la référence qui est faite (mais toujours pour le pointage de l'objet original).
Aussi le fait que le nom de la variable est la même (mais différent de l'emplacement, de l'oie une nouvelle variable de l'ombre à la précédente) est source de confusion.
C'est de la pure fumée. Si quelque chose est en "lecture seule", puis écrit à il devrait tout faire exploser. L'équipe doit au moins remplacer les appels des méthodes de lecture-seule les instances de structures avec des méthodes qui lève une Exception (et le JIT sait exactement quand une structure est en lecture seule dans le code sécurisé, car il ne peut pas être ref/, si c'est "unboxed" ensuite, c'est une copie, si c'est un paramètre d'une fonction, puis c'est une copie). Qu'est-ce qu'un "c'est possible de le faire, mais nous ne vous ferons pas". La preuve de cela est que les propriétés sont interdits. C'est un synctactical la règle et non pas un "par nécessité" de la règle.
OriginalL'auteur xanatos
Dans l'utilisation de bloc, l'objet est en lecture seule et ne peuvent pas être modifiés ou réaffectés.
vérifier ce lien: http://msdn.microsoft.com/en-us/library/yh598w02.aspx
Cette réponse est incorrecte re: C#, comme il se - la structure ne peut pas être modifiée, mais il peut être muté (son contenu peut être modifié). Mais les structures mutables sont une très mauvaise idée, de toute façon, on peut donc soutenir que cette réponse est plus correct que le langage lui-même. 🙂
Je suis d'accord avec @DanielEarwicker ici.
OriginalL'auteur Emir Akaydın
Je ne suis pas sûr à 100% sur ce, n'importe qui s'il vous plaît corrigez-moi si je me trompe.
La raison que le compilateur permet de modifier les champs d'une classe dans ce scénario, mais pas un struct, est liée à la gestion de la mémoire. Dans le cas d'une classe (j'.e un type de référence), le pas l'objet, mais la référence est lui-même la valeur. Ainsi, lorsque vous modifiez un champ de cet objet, vous ne manipulez pas la valeur, mais un bloc de mémoire quelque part d'autre, référencé par la valeur. Dans le cas d'une struct, l'objet est la valeur, de sorte que lorsque vous manipulez un champ dans la structure, vous êtes en fait de la manipulation de la valeur qui est considéré comme étant en lecture seule en ce moment.
La raison pour laquelle le compilateur va permettre l'appel d'une méthode (qui à son tour modifie un champ) est tout simplement qu'il ne peut pas analyser assez profondément pour déterminer si la méthode effectue la modification ou pas.
Il y a un (fermé), MS se Connecter à ce sujet, que peut faire la lumière: Ne peut pas attribuer au domaine de la struct avec IDisposable et quand c'est une aide variable CS1654 erreur
using
(etforeach
), à la fois de créer une variable temporaire qui est affecté. Dans le cas de la structure, la valeur est copiée.oui, mais notez que l'OP n'est pas de l'affectation à l'aide de la variable, mais un champ de l'objet (c'est une mutable struct). Ou ai-je mal vous comprendre?
L'OP est de l'affectation à un champ sur une copie de la struct. Bien que, techniquement, le code est valide, le compilateur refuse, car il n'aura pas d'effet (et indique une erreur de logique).
C'est ce qui explique la règle, mais pas la raison derrière la règle. Quel était le problème, ils ont essayé de résoudre par l'introduction de cette règle?
Pour ajouter au commentaire ci-dessus, avec quelques astuces, vous pouvez contourner ces contraintes. Astuce: boîte de types de valeur.
OriginalL'auteur Fredrik Mörk
La structure est marqué comme étant en lecture seule. Vous essayez de modifier une variable de membre public, qui les drapeaux du compilateur en lecture seule et donc interdit.
Toutefois, l'appel à
Set()
est autorisé car le compilateur n'a aucun moyen de savoir l'appel à la mutation de l'état de la structure. Il est, en effet, un astucieux moyen de la mutation d'un readonly valeur!Prendre un coup d'oeil à Eric Lippert du poste de la mutation readonly structs pour plus d'info.
readonly
. Les champs ne sont jamais implicitementreadonly
.Aussi, à l'aide de
Set()
pour muter unreadonly
domaine ne fonctionnera pas. Erreur de compilateur.Au sein de Set (), le champ n'est pas en lecture seule. Cependant, dans l'exemple de la structure d'une instance est en lecture seule car il est dans un
using
bloc. Ce compilateur déduit que n'importe quel domaine public sur la structure sera également en lecture seule.Vous êtes dans l'erreur. Le compilateur ne pas déduire une de ces détails. Vous ne pouvez pas muter un
readonly
champ (remarque, ne parlons pas de valeur sémantique que par les structures maintenant, qui, je suppose que vous faites allusion), sauf dans le constructeur.Un emplacement de stockage d'un type de structure n'est rien de plus ni de moins que les champs de ce type concaténées. Il n'est pas possible d'écrire dans le champs d'une structure (struct) résidant en lecture seule zone de stockage, ni est-il possible de passer d'une lecture seule structure de localisation
ref
paramètre. Depuis les membres de l'instance sur la structure des types de prendrethis
comme unref
paramètre, il n'est pas vraiment possible d'invoquer les membres de l'instance sur les structures. Malheureusement, C# suppose que sireadOnlyStruct.method()
on ne peut pas passerreadOnlyStruct
àmethod
comme unref
paramètre, ...OriginalL'auteur Sean