== vs. Object.Equals(object) in .NET

So, when I was a comparative novice to the novice I am right now, I used to think that these two things were syntactic sugar for each other, i.e. that using one over the other was simply a personal preference. Over time, I'm come to find that these two are not the same thing, even in a default implementation (see this and this). To further confuse the matter, each can be overridden/overloaded separately to have completely different meanings.

Is this a good thing, what are the differences, and when/why should you use one over the other?


string x = "hello";
string y = String.Copy(x);
string z = "hello";

To test if x points to the same object as y:

(object)x == (object)y  // false
x.ReferenceEquals(y)    // false
x.ReferenceEquals(z)    // true (because x and z are both constants they
                        //       will point to the same location in memory)

To test if x has the same string value as y:

x == y        // true
x == z        // true
x.Equals(y)   // true
y == "hello"  // true

Note that this is different to Java. In Java the == operator is not overloaded so a common mistake in Java is:

y == "hello"  // false (y is not the same object as "hello")

For string comparison in Java you need to always use .equals()

y.equals("hello")  // true

MSDN has clear and solid descriptions of both things.

object.Equals method

operator ==

Overloadable Operators

Guidelines for Overriding Equals() and Operator ==

Is this a good thing, what are the differences, and when/why should you use one over the other?

How can it be "good" or "bad" thing? One - method, another - operator. If reference equality is not sufficient, overload them, otherwise leave them as is. For primitive types they just work out of box.