I know that string is immutable and StringBuilder is mutable. But can anybody explain following code output? Since both are reference types, why do they have different results?
String s1 = "hello";
String s2 = "hello";
Console.WriteLine(s1 == s2); //true
Console.WriteLine(Object.ReferenceEquals(s1, s2)); //true
StringBuilder sb1 = new StringBuilder("hello");
StringBuilder sb2 = new StringBuilder("hello");
Console.WriteLine(sb1 == sb2); //false
Console.WriteLine(Object.ReferenceEquals(sb1, sb2)); //false
Because
stringobjects are highly optimized. In particular, since they’re immutable, they can be interned by the compiler to prevent duplication.If you have two different
stringobjects that both represent the exact same string of characters (as in your example), the compiler will recognize that and maintain only one instance of the actual string object.The result is that both the
s1ands2objects actually are the same object as far as the compiler is concerned and even reference the same location in memory.This bookkeeping happens behind the scenes in something called an “intern table”, but that’s not really something you need to worry yourself with. The important thing is that all string literals are interned by default by the compiler.
The same kind of thing does not happen for
StringBuilderobjects, because they are not immutable. They’re designed to allow you to modify a string object, and as such, the optimizations don’t make much sense. That’s why yoursb1andsb2objects are actually seen as two different objects.The rule of thumb is quite simple: Use
stringby default, or when you want a single immutable string of characters. Only useStringBuilderwhen you want to modify the same string multiple times, say in a loop or other relatively short section of code.Relevant reading: Optimizing C# String Performance