8
votes

Différence entre modifier une variable et une propriété

Il y a probablement une explication assez logique à cela, mais j'ai une question.

Disons que j'ai une variable de type rectangle appelé _rect. Je peux maintenant dire _rect.x = 50; sans aucun problème.

Maintenant, j'ai une classe avec une propriété appelée rection qui expose la variable interne _rect.

Puis, si j'essaie d'écrire rect.x = 50; i Obtenez l'erreur de compilation suivante:

ne peut pas modifier la valeur de retour de 'testclass.rect' car il n'est pas une variable.

i peut écrire rectangle = nouveau rectangle (50, rectangle, rect.width, rect.height) Comme pour un type immuable, mais pour les types non immuables, y a-t-il d'autre moyen de faire cela?

Je veux utiliser les propriétés automatiques de ce champ rectangle, mais c'est vraiment ennuyeux de ne pas pouvoir le modifier à l'intérieur de la classe elle-même.

Y a-t-il un moyen de faire un champ de support et de déposer la propriété automatique?


5 commentaires

Pouvez-vous nous montrer votre code pour la classe RED? Et pourquoi n'utilisez-vous pas la classe rection intégrée?


Est rectangle une classe ou une structure? Si c'est une structure, essayez de le faire une classe


Donnez-nous une liste de code complète, il m'est difficile d'imaginer ce que vous dites et cela aiderait à clarifier votre question.


Désolé pour la confusion ici. RECH est un système standard.Drawing.Rectangle. J'ai mis à jour ma question pour supprimer la confusion.


Voir aussi cette question (non-duplicate):

4 Réponses :


1
votes

Accéder à la propriété est vraiment un appel de fonction qui renvoie une copie du type de valeur. Rect.x = 50; ne modifierait que cette copie temporaire, pas le champ de support lui-même.

Lorsque la propriété n'est pas auto-implémentée, vous pouvez créer une propriété supplémentaire RecTX, qui peut être utilisée pour obtenir et définir la propriété X du rectangle.


2 commentaires

Je me sens vraiment stupide maintenant, pour ne pas comprendre pourquoi le nouveau rectangle (...) a fonctionné et non rect.x = 50, puisque les deux auraient travaillé sur la copie, mais quand j'écris un nouveau rectangle, j'appelle l'ensemble au lieu de avoir. Merci de faire clairement ma propre tête à ce sujet. De sorte que cela signifie fondamentalement non alors. Si je veux ce type de comportement, je dois utiliser un champ de support.


Lors de l'utilisation d'un champ de support, le comportement sera toujours identique, le getter et le setter continuent d'être des méthodes, vous recevrez donc une copie de valeur de l'instance rectangle. Le comportement que vous souhaitez est uniquement pour les types de référence, car vous obtenez alors la "référence" à l'instance d'objet d'origine. Cependant, le rectangle est un type de valeur.



10
votes

La raison de cette erreur est parce que Rectangle est un type de valeur (structure) contrairement aux types de référence (classes). Vous ne pouvez pas modifier la propriété x car lorsque vous utilisez la propriété La propriété getter une nouvelle valeur pour le rectangle est renvoyée (le getter est une fonction). Si c'était un type de référence, vous manipulez le pointeur et cela serait possible.

Il s'agit d'un aspect important des types de référence de valeur VS à conscience de.


5 commentaires

Pour être sûr, il n'y a pas de raison technique pourquoi le compilateur ne pouvait pas faire ce travail. Le compilateur génère toutes sortes de code supplémentaires pour l'utilisateur (par exemple la boxe), alors pourquoi pas ici? (En fait, la raison est probablement que ce n'est pas considéré comme important puisque les structures devraient être immuables de toute façon.)


@Konrad - Les structures sont copiées lorsqu'elles sont transmises en conséquence, de sorte que l'opération n'aurait tout simplement aucun sens. Ce n'est pas à cause de l'immuabilité (les structures sont mutables). Mais si vous récupérez une copie d'un objet et modifiez le champ dans cette copie - c'est simplement un noop.


@Viraptor: Je ne suis pas d'accord. L'opération a évidemment un sens: Mutate une propriété. Le compilateur pourrait facilement faire ce travail en générant du code équivalent à Var TMP = FOO.PROPERTY; tmp.x = newx; foo.property = TMP; - Le compilateur en fait est celui-ci pour une situation équivalente: lorsque vous avez une propriété de type de valeur et écrire foo.property + = 1 Ceci fonctionne (testé sur mono compilateur). Le compilateur réécrit clairement le code à ce qui précède.


@Konrad: Ces cas ne sont pas équivalents - si le type de Propriété est une structure, alors pour foo.property.x + = 1 Vous obtenez l'équivalent de TMP = foo.property; tmp.x + = 1 (où TMP devient une copie copie de la propriété). Si la propriété elle-même est un type de valeur simple, vous ne modifiez rien de la valeur elle-même. Vous générez une nouvelle valeur et assignez à la propriété elle-même, pas une partie de celle-ci. Propriété Getter garantit que vous obtenez la copie du type. Vous obtenez une copie copie de 1 et attribuer le dos 2 par exemple. Si vous obtenez une copie copie de foo.x et modifiez-le, vous attribuez à la copie copie de x .


@Viraptor: Je suis d'accord, je viens de remarquer cette différence moi-même - voir aussi des commentaires ci-dessous Stackoverflow.com/Questtions/441309/whay-are-Mutable-tructs-e Vil / ...



0
votes

0 commentaires

0
votes
  class RectangleWithoutFields 
  {
     // just autoproperties, no fields

     public int X { get; set; }

     public int Y { get; set;}


     public RectangleWithoutFields()
     {
         X = 0;

         Y = 0; 
     }

     public void ChangeProperties(int x, int y)

     {
         X = x;

         Y = y;
     }
 }

1 commentaires

Je n'essayais pas de créer un nouveau rectangle ici, mais pour le faire travailler avec le rectangle standard :)