I see the point in explicitly implementing Equals and GetHashCode for my objects.

But I wonder if it makes any sense to also explicitly implement the == and != operators like this:

public static bool operator ==(Salutation left, Salutation right)
    return Equals(left, right);

Does C# not automatically use the Equals method when == is invoked?

+2  A: 

If you don't overload it, == just checks reference equality: do both sides refer to the same object?

If you need value equality (do different objects on both sides have the same value?), you can overload the operator. At this point, you almost always want to overload .Equals() and .GetHashCode() as well and just have your == overload call .Equals().

Joel Coehoorn
+8  A: 

It does indeed make sense to override the equality operator along with Equals. It is in fact highly advisable.

Microsoft has posted official Guidelines for Implementing Equals and the Equality Operator (==) on MSDN. I would definitely go by the recommended practice there. The two main points are:

  • 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. This allows infrastructure code such as Hashtable and ArrayList, which use the Equals method, to behave the same way as user code written using the equality operator.

Jon Skeet also wrote a useful MSDN blog post about the subject, summarising how Equals and the == operator work by default on reference/value types.

The most important parts are quoted below:

The Equals method is just a virtual one defined in System.Object, and overridden by whichever classes choose to do so. The == operator is an operator which can be overloaded by classes, but which usually has identity behaviour.

For reference types where == has not been overloaded, it compares whether two references refer to the same object - which is exactly what the implementation of Equals does in System.Object.

Value types do not provide an overload for == by default. However, most of the value types provided by the framework provide their own overload. The default implementation of Equals for a value type is provided by ValueType, and uses reflection to make the comparison, which makes it significantly slower than a type-specific implementation normally would be. This implementation also calls Equals on pairs of references within the two values being compared.

Thanks. I accepted your answer, but could you please edit in some of the things Joel said? How == behaves if not overriden.
@Tigraine: No problem. Actually what Joel says (and a good deal more) is all mentioned in the page I linked to, written by Jon Skeet. I'll quote that if you like.
Thanks.. :)It's just easier to read that way ;)
This answer is not entirely correct as overloading the equality operator on reference types is in fact NOT recommended by microsoft (see the link to the guidelines).
Simon Lindgren
@Simon: In general, yes, but not always. The more important guideline is to have == and Equals() do the same thing.
@Noldorin: Fair enough :), I have actually read those recommendations before, and I misread it as a recommendation to always have == and Equals do the same thing. And I do agree that having them do the same thing feels a bit more logical.
Simon Lindgren