Question

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?

Was it helpful?

Solution

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).

OTHER TIPS

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

== 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

Firstly, there is a difference. For numbers

> 2 == 2.0
True

> 2.Equals(2.0)
False

And for strings

> string x = null;
> x == null
True

> x.Equals(null)
NullReferenceException

In both cases, == behaves more usefully than .Equals

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'

== 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 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 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.

Because the static version of the .Equal method was not mentioned so far, I would like to add this here to summarize and to compare the 3 variations.

MyString.Equals("Somestring"))          //Method 1
MyString == "Somestring"                //Method 2
String.Equals("Somestring", MyString);  //Method 3 (static String.Equals method) - better

where MyString is a variable that comes from somewhere else in the code.

Background info and to summerize:

In Java using == to compare strings should not be used. I mention this in case you need to use both languages and also to let you know that using == can also be replaced with something better in C#.

In C# there's no practical difference for comparing strings using Method 1 or Method 2 as long as both are of type string. However, if one is null, one is of another type (like an integer), or one represents an object that has a different reference, then, as the initial question shows, you may experience that comparing the content for equality may not return what you expect.

Suggested solution:

Because using == is not exactly the same as using .Equals when comparing things, you can use the static String.Equals method instead. This way, if the two sides are not the same type you will still compare the content and if one is null, you will avoid the exception.

   bool areEqual = String.Equals("Somestring", MyString);  

It is a little more to write, but in my opinion, safer to use.

Here is some info copied from Microsoft:

public static bool Equals (string a, string b);

Parameters

a String

The first string to compare, or null.

b String

The second string to compare, or null.

Returns Boolean

true if the value of a is the same as the value of b; otherwise, false. If both a and b are null, the method returns true.

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.

There is another dimension to an earlier answer by @BlueMonkMN. The additional dimension is that the answer to the @Drahcir's title question as it is stated also depends on how we arrived at the string value. To illustrate:

string s1 = "test";
string s2 = "test";
string s3 = "test1".Substring(0, 4);
object s4 = s3;
string s5 = "te" + "st";
object s6 = s5;
Console.WriteLine("{0} {1} {2}", object.ReferenceEquals(s1, s2), s1 == s2, s1.Equals(s2));

Console.WriteLine("\n  Case1 - A method changes the value:");
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));

Console.WriteLine("\n  Case2 - Having only literals allows to arrive at a literal:");
Console.WriteLine("{0} {1} {2}", object.ReferenceEquals(s1, s5), s1 == s5, s1.Equals(s5));
Console.WriteLine("{0} {1} {2}", object.ReferenceEquals(s1, s6), s1 == s6, s1.Equals(s6));

The output is:

True True True

  Case1 - A method changes the value:
False True True
False False True

  Case2 - Having only literals allows to arrive at a literal:
True True True
True True True

Adding one more point to the answer.

.EqualsTo() method gives you provision to compare against culture and case sensitive.

Just as an addition to the already good answers: This behaviour is NOT limited to Strings or comparing different numbertypes. Even if both elements are of type object of the same underlying type. "==" won't work.

The following screenshot shows the results of comparing two object {int} - values

Example From VS2017

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.

Really great answers and examples!

I would just like to add the fundamental difference between the two,

Operators such as == are not polymorphic, while Equals 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.

When we create any object there are two parts to the object one is the content and the other is reference to that content. == compares both content and reference; equals() compares only content

http://www.codeproject.com/Articles/584128/What-is-the-difference-between-equalsequals-and-Eq

==

The == operator can be used to compare two variables of any kind, and it simply compares the bits.

int a = 3;
byte b = 3;
if (a == b) { // true }

Note : there are more zeroes on the left side of the int but we don't care about that here.

int a (00000011) == byte b (00000011)

Remember == operator cares only about the pattern of the bits in the variable.

Use == If two references (primitives) refers to the same object on the heap.

Rules are same whether the variable is a reference or primitive.

Foo a = new Foo();
Foo b = new Foo();
Foo c = a;

if (a == b) { // false }
if (a == c) { // true }
if (b == c) { // false }

a == c is true a == b is false

the bit pattern are the same for a and c, so they are equal using ==.

Equal():

Use the equals() method to see if two different objects are equal.

Such as two different String objects that both represent the characters in "Jane"

The only difference between Equal and == is on object type comparison. in other cases, such as reference types and value types, they are almost the same(either both are bit-wise equality or both are reference equality).

object: Equals: bit-wise equality ==: reference equality

string: (equals and == are the same for string, but if one of string changed to object, then comparison result will be different) Equals: bit-wise equality == : bit-wise equality

See here for more explanation.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top