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 :

Comment remplacer un objet par référence dans un IEnumerable ?


Sujet :

C#

  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Août 2005
    Messages
    346
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Août 2005
    Messages : 346
    Points : 119
    Points
    119
    Par défaut Comment remplacer un objet par référence dans un IEnumerable ?
    Bonjour,

    il y a quelque chose que je ne comprends pas avec l'interface IEnumerable et/ou la méthode .Where().

    Je cherche à pouvoir modifier la référence d'un élément de ma collection générique. Si j'utilise l'indexeur numérique, aucun problème. Si j'utilise l'indexeur qui passe par .Where() pour retrouver l'élément, ça ne fonctionne plus.

    Voici mon code d'exemple :

    La classe de mon élément de base:
    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
    class Texte
        {
            private string text = string.Empty;
     
            public string Text
            {
                get
                {
                    return text;
                }
                set
                {
                    text = value;
                }
            }
     
            public Texte(string newText)
            {
                text = newText;
            }
        }
    Ma collection IEnumerable<Texte> qui pose problème :
    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
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    class TexteCollection : IEnumerable<Texte>
        {
            private List<Texte> liste = new List<Texte>();
     
            /// <summary>
            /// Indexeur par index numérique: fonctionne (get et set)
            /// </summary>
            /// <param name="index"></param>
            /// <returns></returns>
            public Texte this[int index]
            {
                get
                {
                    return liste[index];
                }
                set
                {
                    liste[index] = value;
                }
            }
     
            /// <summary>
            /// Indexeur par condition : le set ne fonctionne pas.
            /// </summary>
            /// <param name="text"></param>
            /// <returns></returns>
            public Texte this[string text]
            {
                get
                {
                    IEnumerable<Texte> list = liste.Where(t => t.Text == text);
                    if ( list.Count() > 0 )
                        return list.ElementAt(0);
                    else
                        return null;
                }
                set
                {
                    IEnumerable<Texte> list = liste.Where(t => t.Text == text);
                    if ( list.Count() == 1 )
                    {
                        Texte t = list.ElementAt(0);
                        //t.Text = value.Text;
                        t = value;
                    }   
                }
            }
     
            public void Add(string text)
            {
                liste.Add(new Texte(text));
            }
     
            private IEnumerator<Texte> Enumerator()
            {
                for ( int i = 0; i < liste.Count; i++ )
                {
                    yield return liste[i];
                }
            }
     
     
            #region IEnumerable<Texte> Membres
     
            public IEnumerator<Texte>  GetEnumerator()
            {
                return Enumerator();
            }
     
            #endregion
     
            #region IEnumerable Membres
     
            System.Collections.IEnumerator  System.Collections.IEnumerable.GetEnumerator()
            {
                return Enumerator();
            }
     
            #endregion
    }
    Enfin, un programme Console pour l'exemple :
    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
    class Program
        {
            static void Main(string[] args)
            {
                TexteCollection collection = new TexteCollection();
                collection.Add("test1"); // index 0
                collection.Add("test2"); // index 1
     
                Console.WriteLine("[0]=" + collection[0].Text);
                Console.WriteLine("[1]=" + collection[1].Text);
     
                collection["test1"] = new Texte("test 1 remplacé");
     
                Console.WriteLine("[0]=" + collection[0].Text);
                Console.ReadKey();
            }
        }

    Tel qu'implémenté, la console affiche :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    [0]=test1
    [1]=test2
    [0]=test1
    Alors que la dernière ligne devrait être "[0]=test 1 remplacé".

    Si je modifie le set de mon indexeur dans TexteCollection de cette façon:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    set
                {
                    IEnumerable<Texte> list = liste.Where(t => t.Text == text);
                    if ( list.Count() == 1 )
                    {
                        Texte t = list.ElementAt(0);
                        t.Text = value.Text;
                        // t = value;
                    }   
                }
    Ca fonctionne, j'ai la sortie console:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    [0]=test1
    [1]=test2
    [0]=test1 remplacé
    J'ai l'impression d'avoir oublié quelque chose d'une importance primordiale... mais je ne comprends pas pourquoi cette différence entre
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    t.Text = value.Text;
    et
    Sachant bien évidemment que ce qui m'intéresse est de remplacer mon objet (donc par référence).

    Merci d'avance pour ceux qui m'ont lu, et pour toute aide...
    Bonne journée

  2. #2
    Expert éminent
    Avatar de StormimOn
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2005
    Messages
    2 593
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Sarthe (Pays de la Loire)

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

    Informations forums :
    Inscription : Mai 2005
    Messages : 2 593
    Points : 7 660
    Points
    7 660
    Par défaut
    C'est normal, mais perturbant au premier abord. Pour comprendre il faut regarder comment cela se passe en mémoire. On va le faire en image, c'est plus parlant

    Première étape, tu as ta liste remplie. Tu te retrouves avec ceci

    une liste avec des références vers tes objets test1 et test2.

    Ensuite dans ton code tu fais
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    IEnumerable<Texte> list = liste.Where(t => t.Text == text);
    if (list.Count() == 1)
    {
        Texte t = list.ElementAt(0);
        t = value;
    }
    On va s'intéresser d'abord à la ligne
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Texte t = list.ElementAt(0);
    Voilà ce que tu as en mémoire grosso modo à ce stade

    tu as donc créé une nouvelle référence (t) vers ton objet test1.

    Ensuite lorsque tu fais
    tu modifies la référence créée juste avant. En mémoire tu as alors

    Comme tu peux le constater, la référence à test1 qui se trouve dans la liste n'a jamais été modifiée. D'où le résultat que tu obtiens.

    Pour que cela fonctionne il faudrait faire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    int index = liste.FindIndex(t => t.Text == text);
    if (index != 1)
    {
        liste[index] = value;
    }
    En procédant ainsi, tu modifies effectivement la référence qui se trouve dans la liste. Tu auras ainsi le comportement attendu.

    Edit : vive Paint
    Images attachées Images attachées    

  3. #3
    Rédacteur
    Avatar de The_badger_man
    Profil pro
    Développeur .NET
    Inscrit en
    Janvier 2005
    Messages
    2 745
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Janvier 2005
    Messages : 2 745
    Points : 8 538
    Points
    8 538
    Par défaut
    Que c'est beau


    Concernant la classe Texte, tu as mis une propriété et une fonction pour modifier la valeur de la variable text. En plus du fait d'être inutile, la fonction perturbe car quand on utilise la classe Texte on ne sait pas s'il faut se servir de la propriété ou de la méthode et quelles sont les différences entre les deux.

  4. #4
    Expert éminent
    Avatar de StormimOn
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2005
    Messages
    2 593
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Sarthe (Pays de la Loire)

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

    Informations forums :
    Inscription : Mai 2005
    Messages : 2 593
    Points : 7 660
    Points
    7 660
    Par défaut
    Citation Envoyé par The_badger_man Voir le message
    Que c'est beau
    tsss

    Sinon ce n'est pas une méthode mais un constructeur dans son code

  5. #5
    Rédacteur
    Avatar de The_badger_man
    Profil pro
    Développeur .NET
    Inscrit en
    Janvier 2005
    Messages
    2 745
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Janvier 2005
    Messages : 2 745
    Points : 8 538
    Points
    8 538
    Par défaut
    Effectivement j'étais sûr d'avoir vu un void qui trainait...

  6. #6
    Membre régulier
    Profil pro
    Inscrit en
    Août 2005
    Messages
    346
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Août 2005
    Messages : 346
    Points : 119
    Points
    119
    Par défaut
    Ouaahh , c'est la plus jolie des réponses que j'ai jamais eu dans un forum! Un grand merci StormimOn!

    The_badger_man, effectivement, l'exemple a ses défauts. L'important est qu'on l'ait compris.

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

Discussions similaires

  1. [PowerShell] Comment passer une string "par référence" dans une fonction ?
    Par Plageman dans le forum Scripts/Batch
    Réponses: 7
    Dernier message: 11/11/2010, 15h01
  2. Réponses: 0
    Dernier message: 17/06/2009, 23h26
  3. Comment définir une couleur par ligne dans un objet uicontrol de type Text
    Par VinceDA dans le forum Interfaces Graphiques
    Réponses: 2
    Dernier message: 28/05/2007, 12h13
  4. comment remplacer un caractere par un autre dans un fichier txt
    Par uzumaki_naruto dans le forum Langage
    Réponses: 6
    Dernier message: 24/07/2006, 13h33
  5. [JACOB] Comment passer un objet par référence à une méthode
    Par zlavock dans le forum Entrée/Sortie
    Réponses: 4
    Dernier message: 21/03/2005, 18h28

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