Since both are reference types, why do they have different results?
Because string objects are highly optimized. In particular, since they are immutable, they can be interned by the compiler to prevent duplication.
If you have two different string objects that are the same character string (as in your example), the compiler will recognize this and only support one instance of the actual string object.
As a result, the objects s1 and s2 are actually the same object as the compiler, and even refer to the same place in memory.
This bookkeeping is going on behind the scenes in something called a “worksheet”, but that’s not what you need to worry about. The important thing is that all string literals are interned by default by the compiler.
The same does not happen for StringBuilder objects, because they are not immutable. They are designed so that you can modify the string object, and therefore optimization does not make much sense. Therefore, your sb1 and sb2 actually treated as two different objects.
The rule of thumb is pretty simple: use string by default or when you need one immutable character string. Use only StringBuilder if you want to change the same string multiple times, say, in a loop or another relatively short section of code.
Relevant reading: C # String Performance Optimization
source share