Graviton
Graviton

Reputation: 83244

Overriding Equals and GetHashCode doesn't necessarily override equality overloading operator

I have the following code:

public enum ClassType
{
    I,
    II,

}

public enum LocationType
{
    A,
    B
}
public class Person
{
    public LocationType LocType
    { get; set; }
    public ClassType ClaType
    { get; set; }


    public override bool Equals(object obj)
    {
        Person obPer = obj as Person;
        if (obPer == null)
            return false;
        if (LocType != obPer.LocType)
            return false;
        if (ClaType != obPer.ClaType)
            return false;
        return true;

    }

    public override int GetHashCode()
    {
        return LocType.GetHashCode()^ClaType.GetHashCode();
    }

}

  static void Main(string[] args)
    {

        var p1 = new Person()
        {
            ClaType = ClassType.I,
            LocType = LocationType.A
        };


        var p2 = new Person()
        {
            ClaType = ClassType.I,
            LocType = LocationType.A
        };

        bool isEqual1 = p1.Equals(p2);  //true
        bool getHashCodeNum = p1.GetHashCode() == p2.GetHashCode();  //true
        bool isEqual2 = p1 == p2;  //false
    }

I find that isEqual1=true, getHashCodeNum=true, but isEqual2=false.

I would expect that since I already override Equals and GetHashCode, then the operator == should automatically follow the behavior of Equals, but this is not so. Any reason?

Upvotes: 2

Views: 99

Answers (1)

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 476493

An == is an operator. You can overload the == operator over two Persons as follows:

public class Person {

    //..

    public static bool operator == (Person a, Person b)
    {
        if (Object.ReferenceEquals(a,null) && Object.ReferenceEquals(b,null))
            return true;
        if (Object.ReferenceEquals(a,null) || Object.ReferenceEquals(a,null))
            return false;
        return a.LocType == b.LocType && a.ClaType != b.ClaType;
    }

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

}

== and != are pairs: you need to implement != if you implement == and vice versa, otherwise you get the error:

error CS0216: The operator Person.operator ==(Person, Person) requires a matching operator != to also be defined

Now when you compare two Persons it should work. Mind however that you do not override equality operators, you overload them. So the compiler picks the == implementation (this is not done at runtime through a dynamic binding). As a result:

bool isEqual2 = p1 == p2;  //true
bool isEqual3 = (object) p1 == p2;  //false
bool isEqual4 = p1 == (object) p2;  //false
bool isEqual5 = (object) p1 == (object) p2;  //false

By default the == over two objects is reference equality so only if the two arguments are Persons here, we check whether the two persons are equivalent.

It is therefore probably better to use Equals(..) if you want to check equality with a dynamic binding.

Upvotes: 5

Related Questions