20

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

vgru
  • 49,838
  • 16
  • 120
  • 201
Jui Test
  • 2,399
  • 14
  • 49
  • 76
  • 1
    The Equals() method is *not* just used to compare the content of a string, it can be used to compare *any* two objects. The `string` type in C# *happens* to contain an override method for `Equals()` that will compare their values (this fact is very poorly explained in a number of articles which suggest that `Equals()` is for string comparison only). – Chris Halcrow Sep 25 '18 at 05:01

3 Answers3

27

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)
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • Two questions: why the cast of `d` to `object`, since it's already an object? Also, in the `a Equals b` part, I would call both the object-override, and the string-overload, so it's more clear what the difference is. – doekman Mar 02 '12 at 12:50
  • @doekman: 1) Yes, I don't need the cast in that case. 2) Not sure what you mean. – Jon Skeet Mar 02 '12 at 13:17
  • I mean this: see last anwer. I didn't directly get your explanation about overload/override.... – doekman Mar 02 '12 at 13:35
8

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.

Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
  • It's not *solely* due to interning. Interning is why it would work even if they were declared to be of type `object`. But even references to distinct string objects with the same content would work so long as the compile-time types involved are both string, due to operator overloading. The documentation you've quoted is misleading as it suggests there's some special handling *just for strings* - there isn't, it's just that string is *a* reference type which overloads the == operator. – Jon Skeet Mar 02 '12 at 07:25
  • 1
    Also note that the interning is a language detail - .NET provides the mechanisms, but it would be quite possible to have a language Dumb# which was the same as C# in every way, except without string constant interning. – Jon Skeet Mar 02 '12 at 07:36
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.

Ken Wayne VanderLinde
  • 18,915
  • 3
  • 47
  • 72