Is this a good / effective idiom for implementing equality and equality / inequality operators?

I had a few problems with this, so I wanted to ask if anyone had any feedback on whether this is an efficient way to implement the Equals method and the equality / inequality operators for a custom immutable class. These operators are called very often by my program, so I want to make sure that I understand them correctly.

class MyObj
{

    public static bool operator ==(MyObj a, MyObj b)
    {
        if (!object.ReferenceEquals(a, null))
            return a.Equals(b);
        else if (!object.ReferenceEquals(b, null))
            return b.Equals(a);
        else
            // both are null
            return true;
    }

    public static bool operator !=(MyObj a, MyObj b)
    {
        if (!object.ReferenceEquals(a, null))
            return !a.Equals(b);
        else if (!object.ReferenceEquals(b, null))
            return !b.Equals(a);
        else
            // both are null
            return false
    }

    public override bool Equals(object obj)
    {
        return this.Equals(obj as MyObj);
    }

    public bool Equals(MyObj obj)
    {
        if (object.ReferenceEquals(obj, null))
            return false;
        else
            return (obj.FieldOne == this.FieldOne &&
                    obj.FieldTwo == this.FieldTwo && ...);
    }

}
+3
source share
5 answers

, , , , -, . "Equals" .NET null . , , .

class Foo : IEquatable<Foo>
{
    public override bool Equals(object obj)
    {
        return Equals(obj as Foo);
    }

    public bool Equals(Foo other)
    {
        if (object.ReferenceEquals(other, null)) return false;

        // Optional early out
        if (object.ReferenceEquals(this, other)) return true; 

        // Compare fields here
    }

    public static bool Equals(Foo a, Foo b)
    {
        if (ReferenceEquals(a, null)) return ReferenceEquals(b, null);
        return a.Equals(b);
    }

    public static bool operator ==(Foo a, Foo b)
    {
        return Equals(a, b);
    }

    public static bool operator !=(Foo a, Foo b)
    {
        return !Equals(a, b);
    }
}
+2

, :

  • Equals, GetHashCode.
  • Equals(MyObj) IEquatable<MyObj>, MyObj . Dictionary<> Equals(MyObj), Equals(object).

Trillian, , a != b !(a == b) !Equals(a, b). ( , .)

+2

, , .

Equals(object) Equals(MyObj), . :

public override bool Equals(object obj) {
   MyObj other = obj as MyObj;
   return this.Equals(other);
}

:

public override bool Equals(object obj) {
   return this.Equals(obj as MyObj);
}

, :

public static bool operator !=(MyObj a, MyObj b) {
   return !(a == b);
}
0

, object.ReferenceEquals(foo, null):

(object)foo == null

, .

IEquatable<T> , Equals. Equals(object) Equals(Foo).

public override bool Equals(object other){return Equals(other as Foo);}

:

public static bool operator==(Foo a, Foo b){
    if((object)a == null)
        return (object)b == null;
    return a.Equals(b);
}
public static bool operator!=(Foo a, Foo b){
    return !(a == b);
}

, , , (object)foo == null object.ReferenceEquals(foo, null), , .

0

I prefer to leave all the frames "if it's zero, and then something else ..." for the frame:

class MyObj : IEquatable<MyObj> {

  public static bool operator ==( MyObj left, MyObj right ) {
    return EqualityComparer<MyObj>.Default.Equals( left, right );
  }

  public static bool operator !=( MyObj left, MyObj right ) {
    return !EqualityComparer<MyObj>.Default.Equals( left, right );
  }

  public override bool Equals( object obj ) {
    return this.Equals( obj as MyObj );
  }

  public bool Equals( MyObj other ) {
    return !object.ReferenceEquals( other, null )
        && obj.FieldOne == this.FieldOne
        && obj.FieldTwo == this.FieldTwo
        && ...
        ;
  }

  ...

}

See also. What is the best algorithm for an overridden GetHashCode? for implementation GetHashCode.

0
source

Source: https://habr.com/ru/post/1721586/


All Articles