Reputation: 36583
I've wondered about this, so I figure I'll ask it.
Most places you'll see use the same semantic logic for overriding Equals as GetHashCode for memberwise equality...however they usually use different implementations:
public override bool Equals(object obj)
{
if (obj == null || GetType() != obj.GetType())
{
return false;
}
var other = (MyType)obj;
if (other.Prop1 != Prop1)
{
return false;
}
return true;
}
public override int GetHashCode()
{
int hash = -657803396;
num ^= Prop1.GetHashCode();
return num;
}
If you're implementing memberwise equality for your type (lets say for storing in a dictionary), why not just override GetHashCode then do something like this for Equals:
public override bool Equals(object obj)
{
return this.HashEqualsAndIsSameType(obj);
}
public static bool HashEquals(this object source, object obj)
{
if (source != null && obj != null)
{
return source.GetHashCode() == obj.GetHashCode();
}
if (source != null || obj != null)
{
return false;
}
return true;
}
public static bool HashEqualsAndIsSameType<T>(this T source, object obj)
{
return (obj == null || obj.GetType() == typeof(T)) && source.HashEquals(obj);
}
Upvotes: 5
Views: 876
Reputation: 1063864
Because there is a real risk of conflicts. Hash-codes are not unique. They can (when different) prove inequality, but never equality. When looking for an item:
true
they are the sameConsider long
... since hash-code is int
, it is easy to see that there are lots and lots of conflicts.
Upvotes: 10
Reputation: 21688
Hashes are not 1-to-1, you can have multiple different values that hash to the same value, but which should compare as not equal. So you cannot really implement Equals in terms of GetHashCode. This is why you have collisions in a hash table, and why a hash table lookup must involve call(s) to both GetHashCode and Equals.
Upvotes: 1