IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C# Discussion :

type var et identité d'objet (struc) [Débutant]


Sujet :

C#

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Homme Profil pro
    Enseignant
    Inscrit en
    Janvier 2017
    Messages
    16
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Janvier 2017
    Messages : 16
    Par défaut type var et identité d'objet (struc)
    Bonjour, je débute en C# et en Poo, cela fait beaucoup pour un seul homme.

    J'aimerais m'assurer que j'ai bien compris les concepts de base.

    Je crée deux variables dont l'une est de type var. A celle-ci j'affecte une valeur double, puis j'affecte l'autre variable, d'un autre type (int).

    La variable var devient équivalente à la variable int mais conserve son type de première affectation (double).

    A être équivalentes (i1 == vari1 renvoit true, la méthode equals() pareil), ces deux variables n'en restent pas moins des objets (struct) distincts: pas le même hashcode.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
                int i1 = 3;
                var vari1 =3.2; // vari1 est détecté double
                vari1 = i1;  // vari1 reste double
     
                Console.WriteLine(vari1.Equals(i1)); //True
                Console.WriteLine("vari1: "+ vari1.ToString()+" " +vari1.GetType()); //3 double
                Console.WriteLine("i1: " + i1.ToString() + " " + i1.GetType()); // 3 int
                Console.WriteLine(i1.GetHashCode()+ " vari1 "+vari1.GetHashCode()); // hashcode différents
                bool hcode1 = i1.GetHashCode() == vari1.GetHashCode(); //false
     
                Console.WriteLine(hcode1.ToString()); //false
                Console.WriteLine(i1 == vari1);//True
                Console.Read();

    Par contre, si j'affecte à la variable var le même type que l'autre variable (ici double), le comportement change radicalement: les deux variables deviennent le même objet (struc) puisqu'elles ont le même hashcode.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
                double i2 = 3;
                var vari2 = 3.2; //var est détecté double
                vari2 = i2;  //  i2 et vari2  ayant même type, ils deviennent le même object (ou struct)
     
                Console.WriteLine(vari2.Equals(i2)); //True
                Console.WriteLine("vari2: " + vari2.ToString() + " " + vari2.GetType()); //3 double
                Console.WriteLine("i2: " + i2.ToString() + " " + i2.GetType()); // 3 double
                bool hcode2 = i2.GetHashCode() == vari2.GetHashCode(); //true
                Console.WriteLine(hcode2.ToString());//true
                Console.WriteLine(i2 == vari2);//true
    Ai-je bien tout compris ?

    J'en doute car si je rajoute ces petits bouts de code à la fin:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
                i1 = 4;
                vari1 = 5;
                Console.WriteLine("i1: " + i1 + " -- vari1: " + vari1); // 4 et 5
     
                i2 = 4;
                vari2 = 5;
                Console.WriteLine("i2: " + i2 + " -- vari2: " + vari2); // 4 et 5
                Console.WriteLine(i2.GetHashCode() + " " + vari2.GetHashCode()); // hashcode différents
    i2 et vari2 redeviennent différents, ils n'ont plus le même hashcode.

    D'avance, merci pour vos commentaires.

  2. #2
    Membre averti
    Homme Profil pro
    Enseignant
    Inscrit en
    Janvier 2017
    Messages
    16
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Janvier 2017
    Messages : 16
    Par défaut
    Pour me rassurer quant à ma compréhension de la Poo, quand je travaille selon le même plan avec des objets d'une classe que j'ai créée, là tout se passe comme prévu:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
                Personne p2 = new Personne("Luc");
                Personne p2bis = new Personne();
     
                string st1 = "Avant affectation: p2 " + p2.Nom + " " + p2.GetHashCode() + " -- p2bis " + p2bis.Nom + " " + p2bis.GetHashCode();
     
                p2bis = p2; //j'affecte p2 à p2bis. Ils deviennent le même objet
                string st2 = "Après affectation: p2 " + p2.Nom + " " + p2.GetHashCode() + " -- p2bis " + p2bis.Nom + " " + p2bis.GetHashCode();
     
                p2.Nom = "Lucie"; // Je change le prénom de p2 --> idem  pour p2bis
                p2bis.Nom = "Toto"; // Je change le prénom de p2bis, idem pour p2
                string st3 = "Après changements nom: p2 " + p2.Nom + " " + p2.GetHashCode() + " -- p2bis " + p2bis.Nom + " " + p2bis.GetHashCode();
     
                listSt.Add(st1); listSt.Add(st2); listSt.Add(st3);
                System.IO.File.WriteAllLines(@"C:\test1.txt", listSt);
    Comme prévu, j'obtiens:

    Avant affectation: p2 Luc 34921712 -- p2bis 27973187
    Après affectation: p2 Luc 34921712 -- p2bis Luc 34921712
    Après changements nom: p2 Toto 34921712 -- p2bis Toto 34921712
    p2bis est bien devenu p2. Et que je change le .nom de l'un ou de l'autre, les deux sont affectés puisqu'ils référencent le même objet Personne.
    Ils ne se différencient plus.

    Pourquoi cela ne marchait-il pas avec mes doubles i2 et vari2 dans mon premier post ?
    Parce que ce sont des Structs et pas des Objects ?

    D'avance, merci.

  3. #3
    Membre émérite
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Juillet 2005
    Messages
    562
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Saône et Loire (Bourgogne)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Distribution

    Informations forums :
    Inscription : Juillet 2005
    Messages : 562
    Par défaut
    Bonjour,

    J'ai pas tout à fait compris ou était ton point de blocage, mais ce que je peux te dire c'est que var et de mon point vue pour les développeur fainéant ! Car il permet de typer de façon implicite une variable, c'est à dire que ce n'est pas toi qui lui donne le type, mais le compilateur qui va détecter de quelque type doit être la variable. Mais une fois que le compilateur a détecté que la variable doit être de type double par exemple, cela reste vrai tout au long de l'exécution, et si tu lui affecte un int par exemple, alors il y aura conversion de int vers double. Donc le seul avantage c'est de ne pas avoir à changer le type à la déclaration, lorsque la valeur affectée change de type... bref perso je n'utilise les var que pour des tests rapides, et je mets le bon type lorsque c'est ok, je trouve que le programme gagne en visibilité. Bon ok avec linq c'est plutôt pratique !

    Donc voila une fois que l'on a compris que var n'est qu'un style d'écriture qui au final n'a pas d'impact sur le programme et son fonctionnement alors tes exemples sont tout à fait claire et parlant. Remplace maintenant var par le type qu'il masque, et je pense que tu ne te posera plus de questions.

    De plus à la fin tu dis
    i2 et vari2 redeviennent différents, ils n'ont plus le même hashcode.
    mais tu as fais juste avant
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
        i2 = 4;
        vari2 = 5;
    donc oui ils sont différents

    [EDIT] Désolé j'avais pas vue ton dernier post, regarde du coté de 'type reference' (les object) et 'type valeur' (int, double .. etc) ça devrait t'éclairer.
    [EDIT 2 ]Par contre tu te trompe dans l'interprétation de ton exemple avec les Personnes, ce n'est pas que tu modifie 'les 2 personnes d'un coup' mais tu ne fais plus que référence à une seul et même personne. Donc après p2bis = p2; peut importe que tu appel p2Bis ou p2, les 2 pointes vers le même object et non pas vers 2 object différent, pour t'en rendre compte =>

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
     
    	List<string> listSt = new List<string>();
    	Personne p2 = new Personne("Luc");
       	Personne p2bis = new Personne("");
     	Personne pLuc;
      	string st1 = "Avant affectation: p2 " + p2.Nom + " " + p2.GetHashCode() + " -- p2bis " + p2bis.Nom + " " + p2bis.GetHashCode();
     
    	pLuc = p2;
      	p2bis = p2; //j'affecte p2 à p2bis. Ils deviennent le même objet
     	string st2 = "Après affectation: p2 " + p2.Nom + " " + p2.GetHashCode() + " -- p2bis " + p2bis.Nom + " " + p2bis.GetHashCode();
     	string stLuc = "BackUp de Luc: pLuc " + pLuc.Nom + " " + pLuc.GetHashCode() + " -- p2 " + p2.Nom + " " + p2.GetHashCode();
     
     	p2.Nom = "Lucie"; // Je change le prénom de p2 --> idem  pour p2bis
     	p2bis.Nom = "Toto"; // Je change le prénom de p2bis, idem pour p2
     	string st3 = "Après changements nom: p2 " + p2.Nom + " " + p2.GetHashCode() + " -- p2bis " + p2bis.Nom + " " + p2bis.GetHashCode();
     
     	listSt.Add(st1); listSt.Add(st2); listSt.Add(st3);listSt.Add(stLuc);
     
    //retour => 
    //Avant affectation: p2 Luc 48816357 -- p2bis  37130113
    //Après affectation: p2 Luc 48816357 -- p2bis Luc 48816357
    //Après changements nom: p2 Toto 48816357 -- p2bis Toto 48816357
    //Après affectation: pLuc Luc 48816357 -- p2 Luc 48816357
    donc dans ton exemple tu perds la première personne appelée Luc, elle est en mémoire mais n'est plus accessible.

    J@ck.

  4. #4
    Modérateur
    Avatar de DotNetMatt
    Homme Profil pro
    CTO
    Inscrit en
    Février 2010
    Messages
    3 611
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : CTO
    Secteur : Finance

    Informations forums :
    Inscription : Février 2010
    Messages : 3 611
    Billets dans le blog
    3
    Par défaut
    Citation Envoyé par J@ckHerror Voir le message
    [...] mais ce que je peux te dire c'est que var et de mon point vue pour les développeur fainéant !
    Je ne suis pas d'accord avec toi. var est juste un sucre syntaxique qui permet de typer automatiquement la variable. Il offre plusieurs avantages, parmis lesquels :
    - Les declarations de variables sont alignees, ex:
    Code C# : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    var maVar1 = "monstring";
    var maVar2 = 2.3L;
    var maVarAvecUnLongNom = new MonObjet();
    var maVar = new StringBuilder();
    var maVarAvecUnNomExtrementLongEtComplique = new Namespace1.Namespace2.Class1();
    c'est quand meme un peu plus lisible que :
    Code C# : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    string maVar1 = "monstring";
    long maVar2 = 2.3L;
    MonObjet maVarAvecUnLongNom = new MonObjet();
    StringBuilder maVar = new StringBuilder();
    Namespace1.Namespace2.Class1 maVarAvecUnNomExtrementLongEtComplique = new Namespace1.Namespace2.Class1();
    - Le type etant deja connu, devoir a chaque fois remettre le nom de la classe est parfois lourd
    - Si on veut voir de quel type il s'agit, il suffit de mettre sa souris sur la variable
    - Avec LinQ, a moins de pouvoir eviter tout le temps les types anonymes il n'y a pas vraiment d'autre solution que d'utiliser var (ou a la limite, dynamic mais on perd l'intellisense).

    Apres on ne peut pas utiliser var tout le temps, par exemple si on veut initialiser un type sur son interface (IObject obj = new MyObjectA();), ou encore si on veut juste declarer une variable et l'initialiser au sein d'un block if.

    Bref, je ne pense pas que ce soit pour les feneants, je pense plutot que ca permet de gagner en clarte et en simplicite du code.

    My 2 cents
    Less Is More
    Pensez à utiliser les boutons , et les balises code
    Desole pour l'absence d'accents, clavier US oblige
    Celui qui pense qu'un professionnel coute cher n'a aucune idee de ce que peut lui couter un incompetent.

  5. #5
    Membre Expert
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Novembre 2009
    Messages
    2 056
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Novembre 2009
    Messages : 2 056
    Par défaut
    Pour compléter ce que dit J@ckHerror, il y a une différence entre des variables de types valeurs et celles de types references.
    Les types "classiques" (int,float,bool...) sont des structures, donc des types valeurs. C'est toujours une copie lorsque tu fais une affectation, donc tes variables ne sont jamais les même.
    Tu utilises GetHashCode pour savoir si c'est le même objet mais ce n'est pas le but de cette méthode. Dans ton premier cas Int n’implémente pas de la même manière que Long, donc tu n'as pas le même résultat.

    Pourquoi cela ne marchait-il pas avec mes doubles i2 et vari2 dans mon premier post ?
    Parce que ce sont des Structs et pas des Objects ?
    Donc c'est en partie la bonne réponse, juste un struct est également un objet, mais plus précisément un System.ValueType


    edit:
    La notion de boxing/unboxing peut t'aider a comprendre la difference de traitement des values types : https://msdn.microsoft.com/en-us/library/yz2be5wk.aspx

  6. #6
    Membre averti
    Homme Profil pro
    Enseignant
    Inscrit en
    Janvier 2017
    Messages
    16
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Janvier 2017
    Messages : 16
    Par défaut
    Merci pour vos réponses.
    Cela me parait bien passionnant la Poo, mais ça demande de la concentration !

    J'ai bien appris avec ce concept de boxing/unboxing. Et j'ai pu approfondir la classe mère de toutes, la classe Object.

    En particulier, je retiens sa méthode static : ReferenceEquals()

    Si je veux m'assurer dans mon code que deux appellations d'instance d'une classe référencent le même objet, c'est par là que je dois passer, c'est cela ?

    En l’occurrence dans mon code avec des Personnes: Object.ReferenceEquals(p2, p2bis) qui me renvoit le booléen.

  7. #7
    Membre émérite
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Juillet 2005
    Messages
    562
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Saône et Loire (Bourgogne)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Distribution

    Informations forums :
    Inscription : Juillet 2005
    Messages : 562
    Par défaut
    @DotNetMatt complétement d'accord avec tes remarques (comme toujours !), j'y suis allé un peu fort avec mon fainéant, mais je préfère tout de même qu'il n'y ai pas trop de var dans mon code, bref les gout et les couleurs quoi ...Mais ma remarque était plus dans le sens ou il est débutant, et je pense qu'un débutant devrait plutôt acquérir les bases avant de comprendre pleinement var, qui pour moi peut amener de la confusion, car justement il pourra changer la valeur sans vraiment se rendre compte que le type change, et ce que cela implique.

    @jp2popu oui

    J@ck.

  8. #8
    Membre averti
    Homme Profil pro
    Enseignant
    Inscrit en
    Janvier 2017
    Messages
    16
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Janvier 2017
    Messages : 16
    Par défaut
    Bon je tire toujours le fil de la même pelote...
    Cela me permet d'avancer dans la compréhension fine. Ici Static,Virtual.

    On me dira que p2.equals(p2bis) ferait aussi bien que Object.ReferenceEquals(p2, p2bis).

    Sauf que Equals() est Virtual et que rien n’empêche le concepteur de la classe Personne de le redéfinir.

    Par exemple dans un programme de recherche génétique on définirait que 2 personnes sont Equals si elles ont le même code génétique (vrais jumeaux):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    CodeGenetique untelcode = new CodeGenetique();
    Personne p1JumeauA= new Personne("Louis", untelcode);
    Personne p1JumeauB = new Personne("André", untelcode);
     
    bool a = p1JumeauA.Equals(p1JumeauB); //renverrait true
    bool b = Object.ReferenceEquals(p1JumeauA, p1JumeauB); //renverrait false
    ReferenceEquals() étant une méthode Static non Virtual de la classe Object, je suis sûr à 100% de ce qu'elle fait.

    Dites-le moi si je m'enduis avec de l'erreur lol...

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [Type "var"] Comment récupérer les propriétés de l'objet ?
    Par Firedeal dans le forum Framework .NET
    Réponses: 7
    Dernier message: 31/07/2008, 22h57
  2. Récupérer le nom du type de l'instance d'objet
    Par sony351 dans le forum C++Builder
    Réponses: 1
    Dernier message: 22/02/2007, 23h08
  3. Réponses: 6
    Dernier message: 09/08/2006, 22h35
  4. Identité d'objets
    Par Luc Hermitte dans le forum CORBA
    Réponses: 8
    Dernier message: 25/02/2005, 17h54

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo