3 votes

Pourquoi ce test d'égalité des objets échoue-t-il ?

Prenez la classe et le test unitaire suivants.

public class Entity
    {
        public object Id { get; set; }

        public override bool Equals(object obj)
        {
            return this == (Entity)obj;
        }

        public static bool operator == (Entity base1, Entity base2)
        {
            if (base1.Id != base2.Id)
            {
                return false;
            }

            return true;
        }

        public static bool operator != (Entity base1, Entity base2)
        {
            return (!(base1.Id == base2.Id));
        }
    }

        [TestMethod]
        public void Test()
        {
            Entity e1 = new Entity { Id = 1 };
            Entity e2 = new Entity { Id = 1 };
            Assert.IsTrue(e1 == e2); //Always fails
        }

Quelqu'un peut-il expliquer pourquoi il échoue ?

8voto

Jon Skeet Points 692016

Votre Id est de type object . Lorsque vous construisez deux instances en utilisant 1 comme identifiant pour chacune d'elles, vous obtenez deux objets encadrés différents. Vous comparez ensuite ces objets en utilisant référence l'égalité.

Modifications suggérées pour corriger ce problème :

  • Changez le type de Id pour être de type int si c'est approprié.
  • Utilisez l'option statique object.Equals pour comparer les Ids au lieu de ==

L'un ou l'autre fonctionnera, mais le premier est préférable, selon moi.

Il y a plusieurs autres façons de rendre l'implémentation plus propre si cela vous intéresse, mais je comprends que ce n'est qu'un exemple factice. Juste une liste rapide d'un coup d'oeil :

  • Vous devriez remplacer GetHashCode ainsi que Equals .

  • Votre Equals ne devrait pas effectuer un cast sans condition, car cela déclencherait une exception si l'objet n'est pas du bon type. Si le type est incorrect, retournez false.

  • Votre implémentation actuelle de == peut être simplifiée à juste

    return base1.Id == base2.Id;
  • Votre implémentation == doit effectuer des contrôles de nullité

  • Il est généralement préférable de mettre en œuvre != en renvoyant !(base1 == base2) à moins que vous ne souhaitiez un comportement de spécialiste.

  • Remplacement de Equals dans une classe non scellée peut être problématique. À moins que vous ne prévoyiez un héritage, il vaudrait mieux sceller la classe (IMO - ceci sera probablement controversé).

3voto

bruno conde Points 28120

Parce que vous vous appuyez sur une référence d'objet pour le comparateur :

public object Id { get; set; }

Remplacer

    public static bool operator == (Entity base1, Entity base2)
    {
        if (base1.Id != base2.Id)
        {
            return false;
        }

        return true;
    }

Avec

    public static bool operator == (Entity base1, Entity base2)
    {
        return object.Equals(base1.Id, base2.Id);
    }

2voto

CookieOfFortune Points 8635

Parce que e1.Id et e2.Id sont des objets différents. Même s'ils ont la même valeur, ils ne sont pas le même objet, donc l'opération base1.Id == base2.Id échoue.

2voto

Andy White Points 36586

Votre implémentation de equals ne fait que comparer les références, pas le contenu de l'objet. Vous comparez essentiellement deux pointeurs, et puisque vous avez créé deux objets distincts, votre égalité échouera.

Il existe plusieurs articles sur la façon de mettre en œuvre correctement les égalités, voici un début :

http://weblogs.asp.net/tgraham/archive/2004/03/23/94870.aspx

Pour les entités de la base de données, vous pouvez effectuer une mise en œuvre raccourcie d'Equals en comparant simplement les ID de la base de données, en supposant que deux objets ayant le même ID sont considérés comme "égaux" dans votre système.

2voto

tanascius Points 22712

Votre Id est un objet, pas un int. Pour les objets, l'opérateur == ne vérifie pas l'égalité des valeurs.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X