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 :

Méthode Equals renvoie false ?


Sujet :

C#

  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Février 2007
    Messages
    206
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 206
    Points : 79
    Points
    79
    Par défaut Méthode Equals renvoie false ?
    Bonjour à tous, j'aimerais savoir pourquoi, avec ce code, la méthode Equals me renvoie false. A part les références, je ne vois pas ce qui diffère entre ces deux objets, et je pensais que c'est la méthode ReferenceEquals qui comparent les références, pas Equals. Merci d'avance pour vos lumières

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    List<int> integerList = new List<int>();
    List<int> integerList2 = new List<int>();
    integerList.Add(1);
    integerList2.Add(1);
    Console.Out.WriteLine(integerList.Equals(integerList2));

  2. #2
    Invité
    Invité(e)
    Par défaut
    La méthode te renverra toujours False du fait que List<int> est un type référence donc ta classe List<int> n'implémentant pas ou du moins n'ayant pas rédéfinie la méthode Equals, elle utilisera la méthode du même nom de sa classe de base qui elle vérifie si les deux objets integerList et integerList2 partagent la même référence.

    Tu dois pour pouvoir renvoyer True dans ton cas actuel, créer une classe dérivant de List<int> et redéfinir (à ta propre sauce) la méthode Equals.

  3. #3
    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 : 43
    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 753
    Points
    39 753
    Par défaut
    L'implémentation par défaut de Equals teste l'égalité des références, et comme Equals n'est pas redéfinie dans List<T>, c'est ce qui est utilisé ici.

    Pour tester si deux listes sont "égales", tu peux utiliser la méthode d'extension SequenceEqual de Linq :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Console.Out.WriteLine(integerList.SequenceEqual(integerList2));
    (tient compte de l'ordre)

    Pour ne pas tenir compte de l'ordre, tu peux faire quelque chose comme ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Console.Out.WriteLine(!integerList.Except(integerList2).Any());

  4. #4
    Invité
    Invité(e)
    Par défaut
    +1000.

    Je ne suis pas l'initiateur du thread mais j'ai remarqué qu'avec tes réponses, j'apprend toujours des trucs.

    J'étais parti, avec ma première réponse, créer une classe personnalisée dérivant de List<T> et redéfinissant la méthode Equals. Bref j'allais réinventer la roue quoi.

    Merci.

  5. #5
    Modérateur

    Homme Profil pro
    Chef de projet NTIC
    Inscrit en
    Avril 2007
    Messages
    1 996
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Chef de projet NTIC
    Secteur : Service public

    Informations forums :
    Inscription : Avril 2007
    Messages : 1 996
    Points : 3 106
    Points
    3 106
    Par défaut
    Tomlev : tout comme h2s84, quand j'ai vu la demande j'ai pensé à redéfinir Equals. Et tout comme h2s84, ta méthode à le mérite d'utiliser l'existant.
    Merci pour ce tuyau.

  6. #6
    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 : 43
    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 753
    Points
    39 753
    Par défaut
    Au fait, pour que ça fonctionne, il faut que les éléments de la liste redéfinissent eux-même Equals, sinon ils sont comparés par référence. On peut aussi implémenter IEquatable<T>, ou encore fournir un IEqualityComparer<T> en paramètre de SequenceEqual ou Except

  7. #7
    Membre régulier
    Profil pro
    Inscrit en
    Février 2007
    Messages
    206
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 206
    Points : 79
    Points
    79
    Par défaut
    Merci beaucoup de vos conseils

    J'ai pris comme exemple une list<int> car ça me semblait assez simple. Dans la pratique je dois comparer 2 classes en redéfinissant la méthode equals. La difficulté est que je ne dois pas comparer membre à membre mais que je dois faire appel à la réflexivité. Du coup j'ai écris ç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
    public override bool Equals(object objet)
    {
        PropertyInfo[] propertiesThis = this.GetType().GetProperties();
        PropertyInfo[] propertiesObj = objet.GetType().GetProperties();
     
        if (propertiesThis.Length == propertiesObj.Length)
        {
            for (int i = 0; i < propertiesThis.Length; i++)
            {
                if (!propertiesThis[i].GetValue(this, null).Equals(propertiesObj[i].GetValue(objet, null)))
                {
                    return false;
                }
            }
            return true;
        }
        return false;
    }
    Et bien sûr ça ne fonctionne pas... Je précise que dans cette classe j'ai une classe imbriquée et plusieurs listes d'objets différents (dont une qui contient des instances de la classe imbriquée). Ces listes sont bien déclarées au moyen de propriétés

    A votre avis, existe-il de comparer les classes de cette manière, ou doit-on obligatoirement passer par la comparaison membre à membre ?

  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 : 43
    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 753
    Points
    39 753
    Par défaut
    Pourquoi tu fais comme ça, tu connais pas à l'avance le type des objets à comparer ?

  9. #9
    Membre régulier
    Profil pro
    Inscrit en
    Février 2007
    Messages
    206
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 206
    Points : 79
    Points
    79
    Par défaut
    C'est pour un exercice en fait. Au début j'avais comparé membre à membre et forcément ça marche bien, et comme j'avais de l'avance mon prof m'a dit d'essayer de faire comme ça. Donc j'essaie et ça marche pas des masses pour l'instant^^

    Si je connais les types des objets, mais c'est pour pas énumérer chaque membre quoi

  10. #10
    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 : 43
    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 753
    Points
    39 753
    Par défaut
    Citation Envoyé par scheme Voir le message
    Si je connais les types des objets, mais c'est pour pas énumérer chaque membre quoi
    D'une manière générale, garde quand même à l'esprit qu'utiliser la réflexion est BEAUCOUP plus lent que de comparer les membres directement.

    Cela dit, c'est effectivement un exercice intéressant...

    Tu n'as pas précisé en quoi ça ne marchait pas : exception ? pas le résultat attendu ? A mon avis, la principale raison pour laquelle ton code ne fonctionne pas, c'est le cas où une propriété de l'objet courant (this) est nulle. Dans ce cas l'appel à Equals cause une NullReferenceException.

    Donc il faut gérer le cas où la valeur de la propriété est nulle, et plutôt que de réinventer la roue, autant utiliser ce qui existe déjà : la méthode statique objet.Equals (celle qui prend 2 paramètres)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
                object valueThis = propertiesThis[i].GetValue(this, null);
                object valueObj = propertiesObj[i].GetValue(objet, null);
                if (!object.Equals(valueThis, valueObj))
                {
                    return false;
                }

  11. #11
    Membre régulier
    Profil pro
    Inscrit en
    Février 2007
    Messages
    206
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 206
    Points : 79
    Points
    79
    Par défaut
    Ok mais quelle est la différence avec mon code ?

    En gros j'ai une classe qui une structure qui ressemble à ç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
    class A
    {
        public int attributA { get; set; }
     
        public class B
        {
            public int attributB { get; set; }
     
            public B(int attrB)
            {
                attributB = attrB;
            }
        }
     
        public List<B> listOfB { get; set; }
        public List<int> listOfInt { get; set; }
     
        public A(int attrA)
        {
            attributA = attrA;
            listOfB = new List<B>();
            listOfInt = new List<int>();
        }
    }
    Donc j'ai surchargé la méthode Equals, et ça plante quand ça compare la liste de B. C'est vrai que je n'ai pas géré d'exception... C'est le fait que ce soit une liste ou une liste d'objets d'une classe imbriquée qui pose problème ?

  12. #12
    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 : 43
    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 753
    Points
    39 753
    Par défaut
    Citation Envoyé par scheme Voir le message
    ça plante quand ça compare la liste de B.
    "Ca plante", c'est à dire ? Il y a une erreur ? Ca fait pas ce que tu veux ?

  13. #13
    Membre régulier
    Profil pro
    Inscrit en
    Février 2007
    Messages
    206
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 206
    Points : 79
    Points
    79
    Par défaut
    La comparaison me renvoie false quand ça "passe" sur la liste de B, alors que ça devrait renvoyer vrai (a moins que equals compare les références des listes, auquel cas c'est réglé :s)

  14. #14
    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 : 43
    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 753
    Points
    39 753
    Par défaut
    Citation Envoyé par scheme Voir le message
    La comparaison me renvoie false quand ça "passe" sur la liste de B, alors que ça devrait renvoyer vrai (a moins que equals compare les références des listes, auquel cas c'est réglé :s)
    Ca compare les références, donc c'est normal... chaque instance de A a sa propre instance de List<B>.

Discussions similaires

  1. Méthode execute() qui renvoie 'false'
    Par miabi dans le forum JDBC
    Réponses: 2
    Dernier message: 03/10/2011, 12h14
  2. Réponses: 6
    Dernier message: 04/05/2010, 10h18
  3. Automation Word : CreateDispatch renvoie FALSE
    Par Cram_N7 dans le forum C++
    Réponses: 1
    Dernier message: 12/03/2007, 17h27
  4. isset() me renvoie False
    Par pc.bertineau dans le forum Langage
    Réponses: 13
    Dernier message: 06/03/2007, 12h38
  5. Réponses: 12
    Dernier message: 23/03/2006, 14h13

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