From MSDN
Types that implement IComparable must override Equals.Types that override Equals must also override GetHashCode; otherwise, Hashtable migh
IComparable is an interface that defines that two instances of the implementing class can be seen as greater than, less than or equal to one another. Since you have defined equality in the methods of that interface you also need to override the Equals method (and equality operator) to ensure the results from the two are consistent.
public class EqualityTest : IComparable<EqualityTest>
{
public int Value { get; set; }
public int CompareTo(EqualityTest other)
{
return this.Value.CompareTo(other.Value);
}
}
In the above example I have implemented IComparable, but not overridden Equals. If you call CompareTo with two separate instances of the class that have the same Value it will say there are equal. If you call Equals with the same two instances it will say they are not equal as it will test to see if they are the same object (the default implementation of Equals).
Two equal items should return the same hash code (which are used for quickly finding items used as keys in hash tables) so if you override Equals then you should also override GetHashCode()
As an example I just created the following class in my IDE:
public class EqualityTest
{
public string A { get; set; }
public string B { get; set; }
}
And ran Resharper's helpful "Generate Equality" function saying that I wanted both A and B to affect equality. This is the code it created:
public bool Equals(EqualityTest other)
{
if (ReferenceEquals(null, other))
{
return false;
}
if (ReferenceEquals(this, other))
{
return true;
}
return Equals(other.A, A) && Equals(other.B, B);
}
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj))
{
return false;
}
if (ReferenceEquals(this, obj))
{
return true;
}
if (obj.GetType() != typeof(EqualityTest))
{
return false;
}
return Equals((EqualityTest)obj);
}
public override int GetHashCode()
{
unchecked
{
return ((A != null ? A.GetHashCode() : 0)*397) ^ (B != null ? B.GetHashCode() : 0);
}
}
public static bool operator ==(EqualityTest left, EqualityTest right)
{
return Equals(left, right);
}
public static bool operator !=(EqualityTest left, EqualityTest right)
{
return !Equals(left, right);
}
So if you are overriding Equals then you should also define all of the above to ensure consistency, if you are implementing IComparable then the same applies.
There are two ways that objects in your code could be compared: Equals
and GetHashCode
For your object to be compared properly in ALL situations, when you override the Equals
method (used for some comparisons), you must also override GetHashCode
(used in the rest).
If you override one but not the other, depending on your code, you could get unexpected results.
IComparable is used for comparing two objects - if these are considered equal then Compare will return 0. It would be very unexpected if IComparable.Compare returned zero for two objects, yet obj1.Equals(obj2) returned false since this would imply two different meanings of equality for the objects.
When a class overrides Equals, it should also override GetHashCode since two equal objects should hash to the same value, and this hash should be based on the fields/properties used in the implementation of equality.