0

Equals and == check for reference equality. But it behaves differently why? Here

Console.WriteLine(c == d); //False
Console.WriteLine(c.Equals(d)); //True

Console.WriteLine(cc == dd); //True
Console.WriteLine(cc.Equals(dd));//True

Can somebody explain what happens behind the scene.

    //https://blogs.msdn.microsoft.com/csharpfaq/2004/03/29/when-should-i-use-and-when-should-i-use-equals/
public void StringDoubleEqualsVsEquals()
{
    // Create two equal but distinct strings
    string a = new string(new char[] { 'h', 'e', 'l', 'l', 'o' });
    string b = new string(new char[] { 'h', 'e', 'l', 'l', 'o' });

    Console.WriteLine(a == b); //True
    Console.WriteLine(a.Equals(b)); //True

    // Now let's see what happens with the same tests but with variables of type object
    object c = a;
    object d = b;

    Console.WriteLine(c == d); //False
    Console.WriteLine(c.Equals(d)); //True

    /*************************************************************************/
    Console.WriteLine(Environment.NewLine);
    string aa = "1";
    string bb = "1";

    Console.WriteLine(aa == bb);//True
    Console.WriteLine(aa.Equals(bb));//True

    object cc = aa;
    object dd = bb;

    Console.WriteLine(cc.GetType());//System.String
    Console.WriteLine(dd.GetType());//System.String

    Console.WriteLine(cc == dd);//True
    Console.WriteLine(cc.Equals(dd));//True

    Console.ReadKey();
}
Mong Zhu
  • 23,309
  • 10
  • 44
  • 76
Babu Kumarasamy
  • 329
  • 2
  • 6
  • 15
  • Strings `==` operator checks for value and not references https://msdn.microsoft.com/en-us/library/362314fe.aspx – Allan S. Hansen Jun 24 '16 at 10:44
  • Neither `Equals` nor `==` are guaranteed to test for reference equality. – Lee Jun 24 '16 at 10:45
  • [`==` for strings does a value comparison, NOT a reference comparison.](https://msdn.microsoft.com/en-us/library/system.string.op_equality(v=vs.110).aspx) – Matthew Watson Jun 24 '16 at 10:45
  • To make a long story short: `Equals` is a virtual call, so it will always resolve to `string`'s implementation. `==` is a static non virtual call and overload resolution will find the best match exclusively based on the type of the variables (not the real type of the underlying object). Therefore `c == d` does not resolve to `==(string, string)`. It resolves to `==(object, object)` which performs a reference comparison and therefore returns false. – InBetween Jun 24 '16 at 10:57
  • Then, what the heck is happening with `cc == dd`? Why doesn't it return `false`? That's because `"1"` is a compile time constant and it can be interned; in that case all variables that have been assigned "1" (`aa` and `bb`) are unified and `cc` and `dd` end up pointing to the same exact object; the interned string `"1"`. It follows then that the reference equality check returns `true`. – InBetween Jun 24 '16 at 11:20

1 Answers1

0

The operator == and Object.Equals as such are different things which can be implemented indepentently. Usually, Object.Equals is implemented to check for value equality while == checks for referential equality. However, the operator == on string in fact also checks for value equality.

Codor
  • 17,447
  • 9
  • 29
  • 56
  • I don't follow why you believe the `string` overload of `==` checks for value equality *because* of 'string pooling'. Surely if *all* strings were pooled/interned as you suggest (they aren't) then this would never be required? – Charles Mager Jun 24 '16 at 11:05
  • Is it not the case that there is some internal string pooling? I believed that there is, and hence for strings the referential equality and value equality coincide. – Codor Jun 24 '16 at 11:08
  • 1
    yes, there is - but only for explictly declared string literals, hence the need for value equality for any strings created at runtime. I just didn't really follow the logic in the answer. – Charles Mager Jun 24 '16 at 11:19
  • Thanks for the comment. I made the answer less specific, which in this case also means less misleading. – Codor Jun 24 '16 at 11:25
  • The `==` operator in C# by default performs reference equality. `string` overrides the operator to perform value comparison; interning (or pooling) has nothing to do with this behavior. The fact that `cc == dd` returns `true` *does* have to do with string pooling but that's simply because `"1"` can be interned; `==` is still performing a reference comparison because `cc` and `dd` are typed as `object` and the overload resolution algorithm chooses `==(object, object)` but the comparsion is essentialy `ReferenceEquals(literalOneInterned, literalOneInterned)` which obviously returns `true`. – InBetween Jun 24 '16 at 11:30