C# difference between == and Equals()

I have a condition in a silverlight application that compares 2 strings, for some reason when I use == it returns false while .Equals() returns true.

Here is the code:

if (((ListBoxItem)lstBaseMenu.SelectedItem).Content.Equals("Energy Attack"))
{
    // Execute code
}

if (((ListBoxItem)lstBaseMenu.SelectedItem).Content == "Energy Attack")
{
    // Execute code
}

Any reason as to why this is happening?


When == is used on an expression of type object, it'll resolve to System.Object.ReferenceEquals.

Equals is just a virtual method and behaves as such, so the overridden version will be used (which, for string type compares the contents).


When comparing an object reference to a string (even if the object reference refers to a string), the special behavior of the == operator specific to the string class is ignored.

Normally (when not dealing with strings, that is), Equals compares values, while == compares object references. If two objects you are comparing are referring to the same exact instance of an object, then both will return true, but if one has the same content and came from a different source (is a separate instance with the same data), only Equals will return true. However, as noted in the comments, string is a special case because it overrides the == operator so that when dealing purely with string references (and not object references), only the values are compared even if they are separate instances. The following code illustrates the subtle differences in behaviors:

string s1 = "test";
string s2 = "test";
string s3 = "test1".Substring(0, 4);
object s4 = s3;

Console.WriteLine($"{object.ReferenceEquals(s1, s2)} {s1 == s2} {s1.Equals(s2)}");
Console.WriteLine($"{object.ReferenceEquals(s1, s3)} {s1 == s3} {s1.Equals(s3)}");
Console.WriteLine($"{object.ReferenceEquals(s1, s4)} {s1 == s4} {s1.Equals(s4)}");

The output is:

True True True
False True True
False False True

== and .Equals are both dependent upon the behavior defined in the actual type and the actual type at the call site. Both are just methods / operators which can be overridden on any type and given any behavior the author so desires. In my experience, I find it's common for people to implement .Equals on an object but neglect to implement operator ==. This means that .Equals will actually measure the equality of the values while == will measure whether or not they are the same reference.

When I'm working with a new type whose definition is in flux or writing generic algorithms, I find the best practice is the following

  • If I want to compare references in C#, I use Object.ReferenceEquals directly (not needed in the generic case)
  • If I want to compare values I use EqualityComparer<T>.Default

In some cases when I feel the usage of == is ambiguous I will explicitly use Object.Reference equals in the code to remove the ambiguity.

Eric Lippert recently did a blog post on the subject of why there are 2 methods of equality in the CLR. It's worth the read

  • http://blogs.msdn.com/ericlippert/archive/2009/04/09/double-your-dispatch-double-your-fun.aspx

== Operator

  1. If operands are Value Types and their values are equal, it returns true else false.
  2. If operands are Reference Types with exception of string and both refer to the same instance (same object), it returns true else false.
  3. If operands are string type and their values are equal, it returns true else false.

.Equals

  1. If operands are Reference Types, it performs Reference Equality that is if both refer to the same instance (same object), it returns true else false.
  2. If Operands are Value Types then unlike == operator it checks for their type first and if their types are same it performs == operator else it returns false.

As far as I understand it the answer is simple:

  1. == compares object references.
  2. .Equals compares object content.
  3. String datatypes always act like content comparison.

I hope I'm correct and that it answered your question.