0
        string s1 = "hi";
        string s2 = "hi";
        bool x = (s1 == s2);
        Console.WriteLine(bool.Parse(""+x)); //printed as true and my point of interest
        x = s1.Equals(s2);
        Console.WriteLine(bool.Parse("" + x));//printed as true
        s1 = s2;
        x = (s1 == s2);
        Console.WriteLine(bool.Parse("" + x));//printed as true
        x = s1.Equals(s2);
        Console.WriteLine(bool.Parse("" + x));//printed as true  

Since s1==s2 compares references, it shoukd be returned as false. But i get the output as true. I observe this in case of strings alone. When this is done on objects of other classes, it rightly evaluates to false. Why is this exceptional behaviour observed in strings?

3 Answers3

3

There are two things going on here.

The first is that the string type overloads the == operator. The reference comparison of the == operator is only the default behavior. Any type can overload that operator to get better semantics. If you want to guarantee reference equality, use the ReferenceEquals() method.

The second is something called interning, which allows two different string variables that have the same value to refer to the same object. Interning means that even without the overloaded == operator, if the "hi" literal is interned for both variables, the == and ReferenceEquals() comparisons could still return true

Joel Coehoorn
  • 399,467
  • 113
  • 570
  • 794
  • interning will never change the result of the `==` operator. It might change the performance, and it will change the result of `Object.ReferenceEquals`, but not `==`. – Servy Dec 05 '12 at 17:39
  • @Servy that's true because the operator is overloaded. I was talking about a hypothetical case where the operator is not overloaded, in which case it would change the result. – Joel Coehoorn Dec 05 '12 at 17:42
  • Well, you added that hypothetical after my comment. Before you just discussed using `operator ==` which, as I said, wouldn't result in any different return values. – Servy Dec 05 '12 at 17:45
  • @JoelCoehoorn Even in the hypothetical case then, the result will be the same right? Because the references point to the same string and is evaluated to true?? Or am I understanding wrong? – Nithish Inpursuit Ofhappiness Dec 05 '12 at 17:46
  • @NithishInpursuitOfhappiness that is mostly right... but there is no guarantee that a given string will be interned. – Joel Coehoorn Dec 05 '12 at 17:47
  • @JoelCoehoorn And C# supports this probable interning of strings by default? – Nithish Inpursuit Ofhappiness Dec 05 '12 at 17:49
  • 1
    @NithishInpursuitOfhappiness By default it will only intern compile time literals. Since you define `"hi"` as a literal in code twice, they will both point to the same reference, but if you read the strings in from a file, or the console, etc. and they had the same value they would *not* have the same reference (you can turn on such interning if you want though). They would still be equal when using `operator ==` though, because it compares values. – Servy Dec 05 '12 at 17:54
2

Since s1==s2 compares references

That's a false assumption. You can overload the == operator to do whatever you want.

Here is how you can overload it for your own classes, just like String does.

public class Foo
{
    public int Value { get; set; }
    public static bool operator ==(Foo first, Foo second)
    {
        return first.Value == second.Value;
    }
}
Servy
  • 202,030
  • 26
  • 332
  • 449
2

MSDN string

Although string is a reference type, the equality operators (== and !=) are defined to compare the values of string objects, not references (7.9.7 String equality operators). This makes testing for string equality more intuitive.

Zbigniew
  • 27,184
  • 6
  • 59
  • 66