What is the difference between string and StringBuilder?

I know that string is immutable and StringBuilder is mutable. But can anyone explain the 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 
+6
source share
4 answers

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

+10
source

When you announce

 String s1 = "hello"; String s2 = "hello"; 

the compiler is smart enough to know that the two lines (and always will be) are identical, so it saves "hello" only once and creates s1 and s2 as aliases for the same physical memory. Later, when you test for equality, they are equal, because they are essentially the same variable.

On the other hand, when you announce

 StringBuilder sb1 = new StringBuilder("hello"); StringBuilder sb2 = new StringBuilder("hello"); 

the compiler creates two variables (because they are both mutable, but can be initialized with the same value). It copies the string "hello" to each of them, but now there are 2 copies, because each of them can be subsequently changed. Therefore, despite the fact that their contents are the same, they are two different objects that are located in different places of physical memory, therefore, tests for equality of objects are not performed.

+4
source

By default, when two objects of a reference type are compared, the result is true only if both references are equal, this means that both operands must refer to the same instance of the object. Since the objects referenced by sb1 and sb2 are two different objects, the result of the StringBuilders comparison is false.

But the String class redefines the equality operator in such a way that it does not compare objects by their references, but by their values, because this behavior is very intuitive and expected by programmers. This explains why s1 == s2 returns true.

The reason Object.ReferenceEquals (s1, s2) also returns true (although it seems that s1 and s2 refer to different instances of the string) is called string interning . This causes the CLR to place all occurrences of identical string literals (such as "hallo" and "hallo" in your example) in the internal string pool only once for the application, so both s1 and s2 actually refer to the same instance string "hallo", This is possible because the string is immutable.

+2
source

When you do the following, you are comparing two different StringBuilder objects, not their values:

 StringBuilder sb1 = new StringBuilder("hello"); StringBuilder sb2 = new StringBuilder("hello"); Console.WriteLine(sb1 == sb2); //false 

Here's how you can compare your values:

 Console.WriteLine(sb1.ToString() == sb2.ToString()); 
+1
source

Source: https://habr.com/ru/post/916142/


All Articles