I have a condition in a silverlight application that compares 2 strings, for some reason when I use ==
it returns false while .Equals()
Really great answers and examples!
I would just like to add the fundamental difference between the two,
Operators such as
==
are not polymorphic, whileEquals
is
With that concept in mind, if you work out any example (by looking at left hand and right hand reference type, and checking/knowing if the type actually has == operator overloaded and Equals being overriden) you are certain to get the right answer.
I am a bit confused here. If the runtime type of Content is of type string, then both == and Equals should return true. However, since this does not appear to be the case, then runtime type of Content is not string and calling Equals on it is doing a referential equality and this explains why Equals("Energy Attack") fails. However, in the second case, the decision as to which overloaded == static operator should be called is made at compile time and this decision appears to be ==(string,string). this suggests to me that Content provides an implicit conversion to string.
As far as I understand it the answer is simple:
==
compares object references..Equals
compares object content.String
datatypes always act like content comparison. I hope I'm correct and that it answered your question.
I would add that if you cast your object to a string then it will work correctly. This is why the compiler will give you a warning saying:
Possible unintended reference comparison; to get a value comparison, cast the left hand side to type 'string'
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("{0} {1} {2}", object.ReferenceEquals(s1, s2), s1 == s2, s1.Equals(s2));
Console.WriteLine("{0} {1} {2}", object.ReferenceEquals(s1, s3), s1 == s3, s1.Equals(s3));
Console.WriteLine("{0} {1} {2}", object.ReferenceEquals(s1, s4), s1 == s4, s1.Equals(s4));
The output is:
True True True
False True True
False False True
The ==
token in C# is used for two different equality-check operators. When the compiler encounters that token, it will check whether either of the types being compared has implemented an equality-operator overload for either the specific combination types being compared(*), or for a combination of types to which both types can be converted. If the compiler finds such an overload it will use it. Otherwise, if the two types are both reference types and they are not unrelated classes (either may be an interface, or they may be related classes), the compiler will regard ==
as a reference-comparison operator. If neither condition applies, compilation will fail.
Note that some other languages use separate tokens for the two equality-check operators. In VB.NET, for example, the =
token is used within expressions solely for the overloadable equality-check operator, and Is
is used as a reference-test or null-test operator. An to use =
on a type which does not override the equality-check operator will fail, as will attempting to use Is
for any purpose other than testing reference equality or nullity.
(*)Types generally only overload equality for comparison with themselves, but it may be useful for types to overload the equality operator for comparison with other particular types; for example, int
could have (and IMHO should have but didn't) defined an equality operators for comparison with float
, so that 16777217 would not report itself equal to 16777216f. As it is, since no such operator is defined, C# will promote the int
to float
, rounding it to 16777216f before the equality-check operator sees it; that operator then sees two equal floating-point numbers and reports them as equal, unaware of the rounding that took place.