Var2 = Var1; Var2.prop = x; Résultat : Var1.prop != x.

Messages postés
98
Date d'inscription
vendredi 1 septembre 2006
Dernière intervention
24 octobre 2018
- - Dernière réponse : MGD Software
Messages postés
98
Date d'inscription
vendredi 1 septembre 2006
Dernière intervention
24 octobre 2018
- 26 déc. 2017 à 19:32
Bonjour,
J'ai un petit souci avec les variables objet
Jusqu'à présent, je pensait que quand on faisait Var2 = Var1, les deux variables pointaient sur le même objet.
Toute modification dans l'une se retrouvait dans l'autre.
Or à l'expérience, je me suis rendu compte que ce n'est pas vrai, en tout cas lorsqu'on fait un cast.

Voici mon problème un peu plus détaillé.
Dans un ListView, je mets dans la propriété Tag des ListViewItems une structure ListEntry comportant (entre autres) un membre "action". Ce membre fait partie d'un enum Action qui énumère (!) les différents types d'actions à effectuer quand on clique sur l'item.
Et voici ce qui m'arrive :
ListEntry LE = (ListEntry)Item.Tag;
Console.WriteLine(LE.action);			// Renvoie "create"
LE.action = Action.delete;
Console.WriteLine(((ListEntry)(Item.Tag)).action);	// Renvoie toujours "create"


A priori, le Tag de l'item n'est pas mis à jour.
J'utilise la variable LE pour simplifier le code, qui est beaucoup complexe que ci-dessus. Et je ne suis pas sûr qu'en faisant :
((ListEntry)Item.Tag).action = Action.delete
le tag soit bien mis à jour. D'ailleurs quand j'essaie, j'obtiens : "error CS0445: Impossible de modifier le résultat d'une conversion unboxing"
Par contre, si j'écris
Item.Tag = LE
, ça fonctionne. En fait, j'ai carrément remplacé tout l'objet Tag, au lieu de le modifier. Ce n'est pas vraiment pratique, et dans d'autres cas ça peut ne pas être possible.

Y a-t-il une fonction particulière pour que deux variables pointent vers le même objet, même à travers un cast?
En C et C++, j'utilisais un pointeur. Mais je n'ai pas trouvé l'équivalent en C#.

PS : j'ai été voir ce qu'était le Boxing sur la MSDN, et je n'ai rien compris...
Afficher la suite 

Votre réponse

5 réponses

Messages postés
12421
Date d'inscription
mardi 11 mars 2003
Dernière intervention
18 décembre 2018
0
Merci
Bonsoir,
en C#, les types de bases (sauf string), les enums et les structures sont des types « valeur », c’est à dire qu’ils stockent la valeur de la constantes.
Tous les autres sont des types références (un peu comme les pointeurs).
Tag est un object et object est un type de base.
Une petite verif vite fait sur un site de coding en ligne


Cependant, (et la je ne peux pas vérifier avec le site de coding en ligne) si on place un type reference dans le Tag, je pense que ça devrait marcher.
Dans ton texte tu as dit que ListEntry est une structure, et la struture est un type valeur.

Quand j'étais petit, la mer Morte n'était que malade.
George Burns
Commenter la réponse de Whismeril
Messages postés
12421
Date d'inscription
mardi 11 mars 2003
Dernière intervention
18 décembre 2018
0
Merci
Maitnenant, la bonne question à se poser est : y a t’il besoin du cast?

Si je comprends, l’item en question est du type ListEntry, et tu l’as mis aussi dans le Tag?
Commenter la réponse de Whismeril
Messages postés
98
Date d'inscription
vendredi 1 septembre 2006
Dernière intervention
24 octobre 2018
0
Merci
En effet. C'est quand même pas simple.

J'ai eu le même problème en voulant modifier le membre action dans une List<T>, mais cette fois à la compilation et non à l'exécution :

List<ListEntry> mCompList = new List<ListEntry>();
...
mCompList[i].action = Action.none;      // Erreur CS1612

En allant lire la doc sur l'erreur CS1612, j'ai appliqué la méthode indiquée dans la doc, et ça marche :

ListEntry LE = mCompList[i];
LE.action = Action.none;
mComplist[i] = LE;

CQFD.

Je me demande s'il n'aurait pas été plus simple de créer un classe n'ayant que des membres {get;set;} au lieu d'une structure. Je pense que je n'aurais pas eu ce problème. Mais est-ce plus efficace en terme de vitesse et d’occupation mémoire ? Quelle différence au niveau du code ?
Commenter la réponse de MGD Software
Messages postés
12421
Date d'inscription
mardi 11 mars 2003
Dernière intervention
18 décembre 2018
0
Merci
En terme, d’occupation de mémoire, une classe est un type référence, donc chaque fois qu’elle est « transmise », c’est juste une référence, un pointeur, donc peu de mémoire.
Pour un type valeur, tout ce qu’il contient est copié, donc forcément avec une structure avec plein de champs, chaque copie va prendre beaucoup de place.
En terme de vitesse, je ne sais pas.
Et au niveau du code, ben y a juste {get; set;} en plus.
Commenter la réponse de Whismeril
Messages postés
98
Date d'inscription
vendredi 1 septembre 2006
Dernière intervention
24 octobre 2018
0
Merci
Merci.
Je pense que désormais, j'utiliserai des classes.

J'ai relu l'article de la MSDN sur le boxing, et il en ressort qu'en terme de performance c'est pas le top: le framework n'arrête pas de copier les types valeur dans des objets. Il y a même la démonstration que la modif qu'une variable valeur, passée dans un objet, modifiée dans cet objet et récupérée en valeur n'est en fait pas modifiée. C'est exactement ce qui m'arrive.
https://docs.microsoft.com/fr-fr/dotnet/csharp/programming-guide/types/boxing-and-unboxing

Et pour répondre à la question précédente, le cast est forcément nécessaire pour récupérer la structure :
ListEntry => Tag (boxing) : pas de problème puisque Tag est un objet
Tag => ListEntry (unboxing) : cast obligatoire car l'objet est générique et ne connait pas les membres de la structure.

Bon, j'aurai encore appris quelque chose...

Mais j'apprécie beaucoup en C# la faculté la propriété Tag des contrôles qui en possèdent, qui peut être n'importe quoi, alors qu'en VB6 ce ne pouvait être qu'une chaine, ce qui obligeait à faire des constructions compliquées pour stocker plusieurs valeurs.
Commenter la réponse de MGD Software

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.