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 :

passage par référence d'un attribut d'une classe


Sujet :

C#

  1. #1
    Membre habitué
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2011
    Messages
    107
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Septembre 2011
    Messages : 107
    Points : 132
    Points
    132
    Par défaut passage par référence d'un attribut d'une classe
    Bonjour,

    Tout d'abord un code sommaire de ce que j'essaie de faire.

    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
    24
    25
    26
    27
    28
    29
    30
    31
     
    // j'ai deux classe, A et B.
     
    class A
    {
       public int i = 2;
     
    	/*
    	...
    	*/
    }
     
    class B 
    {
    	private int i;
     
    	void B(ref int i)
    	{
    		this.i = i;
    	}
    }
     
    Le main :
    public static void Main()
    {
    	A a = new A();
     
    	B b = new B(ref A.i);
     
            A.i = 10;
    }
    Mon problème est le suivant :
    lorsque je fais cet appel : "A.i = 10;", seule l'attribut i de A est modifié. Or selon mon code celui de B devrait l'être aussi non puisque c'est censé "être le meme" ?

    Je vous remercie d'avance pour votre aide.

  2. #2
    Membre éclairé
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Septembre 2011
    Messages
    610
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2011
    Messages : 610
    Points : 713
    Points
    713
    Par défaut
    Et pourquoi ne pas appeler le constructeur de la classe B après avoir déclaré i:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
            A a = new A();
            A.i = 10;
    	B b = new B(ref A.i);

  3. #3
    Expert confirmé
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Novembre 2009
    Messages
    2 025
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    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 025
    Points : 5 462
    Points
    5 462
    Par défaut
    Ben pour moi c'est pas parceque t'as fait this.i=i, que c'est la reference qui est copié seulement la valeur.

    En fait le = ne vas pas faire comme avec les autre objets pas de type "valeur", c'est à dire copier la reference, mais bel et bien faire une copie.

  4. #4
    Membre éclairé
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Septembre 2011
    Messages
    610
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2011
    Messages : 610
    Points : 713
    Points
    713
    Par défaut
    Je pense que j'ai mal lu!!
    Ou surement mal compris.
    Mais le i de B ne changera pas de valeur puisque tu t'en sert de reférence pour le i de la classe A, je ne sais pas si cela répond à ta question...

  5. #5
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Points : 39 749
    Points
    39 749
    Par défaut
    On peut passer des paramètres par références, mais pas stocker des références à des champs ou des variables...

  6. #6
    Expert éminent
    Avatar de StringBuilder
    Homme Profil pro
    Chef de projets
    Inscrit en
    Février 2010
    Messages
    4 153
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Chef de projets
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2010
    Messages : 4 153
    Points : 7 403
    Points
    7 403
    Billets dans le blog
    1
    Par défaut
    J'ai jamais été bien fort en pointeur, mais je pense que dans ta classe B, ton "i" est mal déclaré.

    Il faut le mettre dans un bloc unsafe et le déclarer en tant que pointeur.

    Car là, ton "i" est bel et bien une instance d'int et non une référence d'int. Que tu le récupère à partir d'une valeur passée en référence au constructeur ne changera rien.

    Le ref dans ton constructeur n'est ici utile que si tu fais un truc du genre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    	void B(ref int i)
    	{
    		this.i = ++i;
    	}
    => A ce moment, A.i passe à 11 à la sortie de la construction de B lors d'un :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    B b = new B(ref a.i);
    On ne jouit bien que de ce qu’on partage.

  7. #7
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Points : 39 749
    Points
    39 749
    Par défaut
    Citation Envoyé par StringBuilder Voir le message
    J'ai jamais été bien fort en pointeur, mais je pense que dans ta classe B, ton "i" est mal déclaré.

    Il faut le mettre dans un bloc unsafe et le déclarer en tant que pointeur.
    Ca n'a rien à voir avec les pointeurs ; il n'est pas possible de déclarer i de façon à faire ce qu'il veut.

    Le passage par référence dans le constructeur permet de modifier la valeur du paramètre, mais c'est tout. Une fois le constructeur exécuté, il n'y a plus aucun lien entre la classe B et le champ A.i.

    A la rigueur, si le but est de "synchroniser" A.i et B.i, ça pourrait se faire via une propriété

    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
    class A
    {
        public int I { get; set; }
    }
     
    class B
    {
        private readonly A _a;
     
        public B(A a)
        {
            _a = a;
        }
     
        public int I
        {
            get { return _a.I; }
            set { _a.I = value; }
        }
    }
    Mais avec des champs, c'est complètement impossible en C#...

  8. #8
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Points : 39 749
    Points
    39 749
    Par défaut
    Si vraiment tu veux bidouiller avec des pointeurs, tu peux faire un truc comme ça :

    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
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    void Main()
    {
        var a = new A { i = 42 };
        var b = new B(ref a.i);
        Console.WriteLine(b.j); // 42
        a.i = 55;
        Console.WriteLine(b.j); // 55... mais pas forcément
    }
     
    class A
    {
        public int i;
    }
     
    unsafe class B
    {
        public B(ref int i)
        {
            fixed(int* tmp = &i)
            {
                this.i = tmp;
            }
        }
     
        public int* i;
     
        public int j
        {
            get
            {
                return *i;
            }
        }
    }
    Le problème, c'est qu'il n'y a aucune garantie que le pointeur reste valide : le GC peut très bien décider de déplacer l'instance de A en mémoire, et le pointeur pointera alors sur un emplacement non valide (on peut observer ça en introduisant un GC.Collect avant de changer la valeur de a.i)

  9. #9
    Membre éprouvé Avatar de sisqo60
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Février 2006
    Messages
    754
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Indre et Loire (Centre)

    Informations professionnelles :
    Activité : Consultant informatique

    Informations forums :
    Inscription : Février 2006
    Messages : 754
    Points : 1 188
    Points
    1 188
    Par défaut
    Bonsoir,

    Tomlev a tout à fait raison, la première solution qu'il t'a proposé est la meilleure, t'es obligé d'avoir une référence à ton instance d'objet de classe A pour contourner ton problème. La deuxième solution qu'il t'a donnée n'est pas concevable pour les arguments donnés.
    Un âne se croit savant parce qu'on le charge de livres (proverbe américain)

    N'oubliez pas de avant de
    Pas de question techniques par MP, c'est contre la philosophie du forum

  10. #10
    Membre habitué
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2011
    Messages
    107
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Septembre 2011
    Messages : 107
    Points : 132
    Points
    132
    Par défaut
    Bonsoir.

    Pardon pour ma réponse tardive.
    J'ai résolu le problème en encapsulant mon entier dans un objet qui ne contient que celui ci.

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

Discussions similaires

  1. Réponses: 5
    Dernier message: 21/03/2012, 18h12
  2. Réponses: 1
    Dernier message: 29/08/2011, 17h31
  3. Réponses: 4
    Dernier message: 26/12/2009, 20h48
  4. Passage par référence d'une référence
    Par Clercq dans le forum Débuter
    Réponses: 4
    Dernier message: 17/04/2009, 18h11
  5. Réponses: 4
    Dernier message: 26/12/2005, 17h01

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