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 :

Dictionary<string, MyStruct> - Problème de référence ?


Sujet :

C#

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Octobre 2007
    Messages
    21
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Octobre 2007
    Messages : 21
    Points : 13
    Points
    13
    Par défaut Dictionary<string, MyStruct> - Problème de référence ?
    Bonjour à tous,

    Je me trouve devant un problème que je n'arrive pas à résoudre, j'espère que vous pourrez m'aider

    J'ai réduit le problème à un petit programme simple, histoire d'avoir l'essentiel :

    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
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
     
    namespace XmlNodeTest
    {
        class MainClass
        {
            public static void Main(string[] args)
            {
                Dictionary<string, MyStruct> myDictionary = new Dictionary<string, MyStruct>();
                myDictionary.Add("1", new MyStruct(24));
                Console.WriteLine(myDictionary["1"].I); // I wait for 24
                Console.WriteLine(myDictionary["1"].J); // I wait for 0
     
                MyStruct m = myDictionary["1"]; // Take the reference, through the dictionary, to the struct I just created
     
                Calcul(m); // Make some work and modify the J value
                Console.WriteLine("Result of modifications : "+myDictionary["1"].J); // Want to see the result : I wait for 999 but 0 !!!
            }
            public static void Calcul(MyStruct myStruct)
            {
                int result = 999;
                myStruct.J = result;
            }
        }
     
        public struct MyStruct
        {
            private int i;
            private int j;
     
            public MyStruct(int i)
            {
                this.i = i;
                j = 0;
            }
     
            public int I
            {
                get { return i; }
                set { i = value; }
            }                
     
            public int J
            {
                get { return j; }
                set { j = value; }
            }
        }
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    Sortie Console :
    24
    0
    Result of modifications : 0
    Mon problème est le suivant : Je créé un Dictionary avec un string comme clé et un MyStruct (que je créé moi-même) en valeur. J'ajoute une paire de clé/valeur à mon dictionnaire ("1", new MyStruct(24)) et je consulte les deux variables de mon struct (I et J) Jusque là, impeccable.

    Mon but est, par la suite, quelques temps plus tard, de retrouver la référence de ce struct par sa clé (MyStruct m = myDictionary["1"]) et de pouvoir modifier la valeur de I ou de J par une méthode de Calcul (Calcul(m)). Le code se compile mais à l'exécution, quand je vérifie la valeur de J après sa "modification", je retrouve 0 et je ne sais pas pourquoi.

    C'est peut-être un problème de référence mais d'une part je ne sais pas où et d'une autre part je ne saurais pas pourquoi, tout semble logique pourtant

    Et si j'essaye de modifier la valeur par une commande plus "rapide", du genre myDictionary["1"].J = 999, le code ne se compile tout simplement pas et m'affiche l'erreur
    "Cannot modify a value type return value of "... Dictionary<...,...>. Consider storing the value in a temporary variable"
    ... ce que je tente de faire donc.

    Une idée du pourquoi je n'arrive pas à modifier ma variable J ?

    Merci d'avance pour votre réponse,

    ++
    thegitch

  2. #2
    Membre régulier
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2007
    Messages
    257
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Décembre 2007
    Messages : 257
    Points : 74
    Points
    74
    Par défaut
    Ok je crois avoir compris.
    En fait, en .NET une structure n'est pas un type référence mais un type valeur.
    Dans ton cas, tu passe en argument à la fonction Calcul ta structure à modifier mais vu que l'argument est de type valeur, il est passé en argument par valeur, ce qui veut dire que la fonction Calcul va faire une copie de ta structure et travailler dessus(la structure originale n'étant pas modifiée).

    La solution est d'utiliser les mot clé ref ou out pour préciser que tu veux passer ton type valeur par référence et non par valeur :
    Dans ton cas :
    Pour la définition de la fonction:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    public static void Calcul(ref MyStruct myStruct)
            {
                int result = 999;
                myStruct.J = result;
            }
    et pour l'appel à Calcul :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Calcul(ref m); // Make some work and modify the J value
    La différence entre ref et out est qu'avec out, on peut passer par référence une variable de type valeur qui n'a pas été initialisé.

    Sinon, le meme problème se pose mais à la ligne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    MyStruct m = myDictionary["1"];
    En fait, en faisant myDictionary["1"] tu accédes à ta structure mais quand tu l'affecte à la variable m par contre, ce n'est pas la structure meme que tu affectes mais une copie. Le mieux que je te conseille pour tous les problèmes que tu rencontres là est d'utiliser une classe au lieu d'une structure. Dans ce cas, plus besoin des mots clés ref et out.

  3. #3
    Membre actif Avatar de gdkenny
    Profil pro
    Inscrit en
    Juillet 2005
    Messages
    251
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Juillet 2005
    Messages : 251
    Points : 248
    Points
    248
    Par défaut
    Tu as besoin d'un type qui a un comportement de type référence.

    Au lieu d'utiliser le mot clé ref sur un type valeur, tu pourrais remplacer ta structure par une classe

  4. #4
    Expert éminent sénior Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 175
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 175
    Points : 25 116
    Points
    25 116
    Par défaut
    Citation Envoyé par gdkenny Voir le message
    Tu as besoin d'un type qui a un comportement de type référence.

    Au lieu d'utiliser le mot clé ref sur un type valeur, tu pourrais remplacer ta structure par une classe
    +1


    y a une recrudescence en ce moment de structure, je pensais en trouver moins chez vous (=c#, étant vb-iste) mais vous êtés touchés aussi ...

  5. #5
    Membre actif Avatar de gdkenny
    Profil pro
    Inscrit en
    Juillet 2005
    Messages
    251
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Juillet 2005
    Messages : 251
    Points : 248
    Points
    248
    Par défaut
    En venant du C/C++ c'est pas évident non plus: en c++ les paramètres formels passés par référence (pointeur ou référence) doivent être marqués par des mots clés.

    en C# les classes sont passées par défaut par référence!

    Et en C, la struct est reine...

Discussions similaires

  1. [VBA-E] Problème de références
    Par Elstak dans le forum Macros et VBA Excel
    Réponses: 13
    Dernier message: 13/07/2006, 09h04
  2. Problème de référence de classe
    Par nmathon dans le forum Delphi
    Réponses: 7
    Dernier message: 21/06/2006, 16h46
  3. [FLASH MX2004] this et problème de référence
    Par cristolb dans le forum ActionScript 1 & ActionScript 2
    Réponses: 5
    Dernier message: 03/05/2006, 22h33
  4. Problème de référence de données circulaire
    Par Wismerhill50 dans le forum Langage
    Réponses: 3
    Dernier message: 23/10/2005, 22h38
  5. problème de références _ptr dans une map STL
    Par Mr_Tyu dans le forum CORBA
    Réponses: 1
    Dernier message: 10/08/2004, 10h39

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