Difference between == operator and Equals() method in C#?
What is the difference between ==
and Equals()
with example? I know that ==
is used to compare operator and Equals()
method is used to compare content of string.So i tried
// first example
string s1 = "a";
string s2 = "a";
Console.Write(a.Equals(s2)); // returns true, but if I assign "b" to s2,
// then result will be false
// second example
string s1 ="a";
string s2 ="a";
Console.Write(s1 == s2); // returns true
How this is so? Both are different object references. Suppose we consider that these are reference. But I tried to use like this
string s1 = new string("ab");
string s2 = new string("ab");
I am getting compile time error that can not convert string to char
Solution 1:
There are several things going on. Firstly, in this example:
string s1 = "a";
string s2 = "a";
Console.WriteLine(s1 == s2);
You claim that:
Both are different object reference.
That's not true due to string interning. s1
and s2
are references to the same object. The C# specification guarantees that - from section 2.4.4.5 of the C# 4 specification:
When two or more string literals that are equivalent according to the string equality operator (§7.10.7) appear in the same program, these string literals refer to the same string instance.
So in this particular case, you would still get "true" even if you printed object.ReferenceEquals(s1, s2)
, or if you made it use a true reference identity comparison with ==
:
object s1 = "a";
object s2 = "a";
Console.WriteLine(s1 == s2); // Still prints True due to string literal interning
However, even if these were references to separate objects, ==
is overloaded for string
. Overloading is a compile-time decision - the implementation to use depends on the compile-time types of the operands. So for example:
string a = new string('x', 1);
string b = new string('x', 1);
Console.WriteLine(a == b); // Uses string's implementation, prints True
object c = a;
object d = b;
Console.WriteLine(c == d); // Reference identity comparison, prints False
Compare that with object.Equals(object)
which is a virtual method. As it happens, String
overloads this method as well, but importantly it overrides it. So if we change our code to:
string a = new string('x', 1);
string b = new string('x', 1);
Console.WriteLine(a.Equals((object) b));
object c = a;
object d = b;
Console.WriteLine(c.Equals(d));
... then both method calls in the compiled code will simply be to object.Equals(object)
, but they'll still both print True because of polymorphism: the implementation in String
will be used.
Here's what a call to the overloaded method would look like:
string a = new string('x', 1);
string b = new string('x', 1);
Console.WriteLine(a.Equals(b)); // Calls string.Equals(string)
Solution 2:
Quote from the documentation of Equals:
The default implementation of Equals supports reference equality for reference types, and bitwise equality for value types. Reference equality means the object references that are compared refer to the same object. Bitwise equality means the objects that are compared have the same binary representation.
And the == operator:
For predefined value types, the equality operator (==) returns true if the values of its operands are equal, false otherwise. For reference types other than string, == returns true if its two operands refer to the same object. For the string type, == compares the values of the strings.
Now back to your question: why does s1 == s2
returns true? Strings are special beasts in .NET. They represent immutable reference types. They are interned in .NET. This means that if you have 2 string constants with the same value, they will refer to the same object instance at runtime.
Quote from the documentation:
The common language runtime conserves string storage by maintaining a table, called the intern pool, that contains a single reference to each unique literal string declared or created programmatically in your program. Consequently, an instance of a literal string with a particular value only exists once in the system.
Solution 3:
You're thinking seem Java-esque. In java, the ==
operator cannot be customized, so for reference types, it always means reference equality, while it means value equality for primitive types. On the other hand, Equals
is for checking value equality in reference types.
Things are different in C#, though. Both Equals
and ==
can have custom implementations. The difference is that Equals
is a virtual (instance) method, while operator==
is a static method. Aside from that, they can behave in exactly the same way.
By default, both Equals
and ==
check reference equality for reference types, and value equality for value types. However, for string
, both are customized to check value equality.