What's wrong with defining operator == but not defining Equals() or GetHashCode()?

user541686 picture user541686 · May 28, 2012 · Viewed 18.7k times · Source

For the code below

public struct Person
{
    public int ID;
    public static bool operator ==(Person a, Person b) { return  a.Equals(b); }
    public static bool operator !=(Person a, Person b) { return !a.Equals(b); }
}

Why does the compiler give me these warnings?
What's wrong with not defining the methods below?

warning CS0660: 'Person' defines operator == or operator != but
    does not override Object.Equals(object o)

warning CS0661: 'Person' defines operator == or operator != but
    does not override Object.GetHashCode()

Answer

Matthew Flaschen picture Matthew Flaschen · May 28, 2012

EDIT: This answer has been corrected, among other things to note that user-defined value types don't generate ==, and to mention the performance issues with ValueType.Equals.


In general, overridding one, but not all, is confusing. The user expects neither to be overridden, or both to be, with the same semantics.

Microsoft's recommendations for this state (among other things):

  • Implement the GetHashCode method whenever you implement the Equals method. This keeps Equals and GetHashCode synchronized.

  • Override the Equals method whenever you implement the equality operator (==), and make them do the same thing.

In your case, you have a valid reason to defer to Equals (the compiler doesn't automatically implement ==) and override only those two (==/!=). However, there's still a performance issue, since ValueType.Equals uses reflection:

"Override the Equals method for a particular type to improve the performance of the method and more closely represent the concept of equality for the type."

Thus, it's still recommended to override all (==/!=/Equals) in the end. Of course, performance may not matter for this trivial struct.