Opérateur de surcharge= = versus égal()

je travaille sur un projet C# sur lequel, jusqu'à présent, j'ai utilisé des objets immuables et des usines pour s'assurer que les objets de type Foo peut toujours être comparé pour l'égalité avec ==.

Foo les objets ne peuvent pas être changés une fois créés, et l'usine renvoie toujours le même objet pour un ensemble donné d'arguments. Cela fonctionne très bien, et tout au long de la base de code nous supposons que == fonctionne toujours pour vérifier l'égalité.

maintenant j'ai besoin d'ajouter fonctionnalité qui introduit un cas de bord pour lequel cela ne fonctionnera pas toujours. La meilleure chose à faire est de surcharge operator == pour ce type, de sorte qu'aucun autre code dans le projet qui doit changer. Mais cela me frappe comme une odeur de code: la surcharge operator == et non Equals semble juste bizarre, et je suis habitué à la convention que == vérifie l'égalité des références, et Equals vérifie l'égalité de l'objet (ou quel que soit le terme).

Est-ce une préoccupation légitime, ou devrais-je simplement aller de l'avant et de surcharge <!--4?

42
demandé sur Paul Roub 2009-11-20 00:00:12

6 réponses

je crois que la norme est que pour la plupart des types .Equals vérifie la similarité des objets, et l'opérateur == vérifie l'égalité des références.

je crois que la meilleure pratique est que pour immuable types, l'opérateur == devrait vérifier la similarité, aussi bien que .Equals. Et si vous voulez savoir si elles sont vraiment le même objet, utilisez .ReferenceEquals. Voir le C# String classe pour un exemple de cette.

27
répondu McKay 2013-03-12 13:22:16

Il y a une grande différence entre surcharge== et prépondérant égal.

quand vous avez l'expression

if (x == y) {

La méthode qui sera utilisée pour comparer les variables x et y est décidé à compiler fuseau. C'est la surcharge d'opérateur. Le type utilisé pour déclarer x et y est utilisé pour définir quelle méthode est utilisée pour les comparer. Le type réel à l'intérieur de x et y (c.-à-d. une sous-classe ou une mise en œuvre de l'interface)) n'est pas pertinent. Considérons l'exemple suivant.

object x = "hello";
object y = 'h' + "ello"; // ensure it's a different reference

if (x == y) { // evaluates to FALSE

et

string x = "hello";
string y = 'h' + "ello"; // ensure it's a different reference

if (x == y) { // evaluates to TRUE

Cela démontre que le type utilisé pour déclarer les variables x et y est utilisé pour déterminer la méthode utilisée pour évaluer ==.

en comparaison, les égaux sont déterminés à exécution basé sur le type réel dans la variable X. Equals est une méthode virtuelle sur un objet que d'autres types peuvent, et font, outrepasser. Par conséquent, les deux exemples suivants à la fois évaluer la valeur true.

object x = "hello";
object y = 'h' + "ello"; // ensure it's a different reference

if (x.Equals(y)) { // evaluates to TRUE

et

string x = "hello";
string y = 'h' + "ello"; // ensure it's a different reference

if (x.Equals(y)) { // also evaluates to TRUE
83
répondu Samuel Neff 2016-06-19 18:51:12

ça sent vraiment mauvais. En cas de surcharge == vous devez vous assurer que Equals() et GetHashCode() sont également compatibles. Voir le lignes directrices du MSDN.

et la seule raison pour laquelle cela semble correct est que vous décrivez votre type comme immuable.

7
répondu Henk Holterman 2009-11-19 22:18:13

pour les types immuables Je ne pense pas qu'il y ait quelque chose de mal à avoir == surchargé pour soutenir l'égalité des valeurs. Je ne pense pas que je voudrais remplacer == sans écraser Equals pour avoir la même sémantique. Si vous ne remplacer == et le besoin de vérifier la référence de l'égalité, pour une raison quelconque, vous pouvez utiliser Object.ReferenceEquals(a,b).

Voir le Microsoft article de quelques lignes directrices utiles

7
répondu Mike Sackton 2013-03-12 13:23:17

exemple montrant comment implémenter ceci selon MSFT guidelines (ci-dessous). Remarquez, lorsque vous écrasez égal, vous devez aussi outrepasser GetHashCode (). Espérons que cela aide les gens.

public class Person
{
    public Guid Id { get; private set; }

    public Person(Guid id)
    {
        Id = id;
    }

    public Person()
    {
        Id = System.Guid.NewGuid();
    }

    public static bool operator ==(Person p1, Person p2)
    {
        bool rc;

        if (System.Object.ReferenceEquals(p1, p2))
        {
            rc = true;
        }
        else if (((object)p1 == null) || ((object)p2 == null))
        {
            rc = false;
        }
        else
        {
            rc = (p1.Id.CompareTo(p2.Id) == 0);
        }

        return rc;
    }

    public static bool operator !=(Person p1, Person p2)
    {
        return !(p1 == p2);
    }

    public override bool Equals(object obj)
    {
        bool rc = false;
        if (obj is Person)
        {
            Person p2 = obj as Person;
            rc = (this == p2);
        }
        return rc;
    }

    public override int GetHashCode()
    {
        return Id.GetHashCode();
    }
}
6
répondu John 2016-09-16 19:17:51

selon les meilleures pratiques de Microsofts, le résultat de la méthode des égaux et de la surcharge des égaux ( = = ) devrait être le même.

CA2224: Remplacement est égal à la surcharge de l'opérateur égal à

4
répondu Ykok 2016-09-16 19:47:06