2nd option would be faster.
The performance difference is not just because strings are immutable and StringBuilder is mutable. Even if the String were mutable, the performance difference would have been there, and that’s because of how it is used in the function.
Assume for a moment that String is mutable and the same statement is used:
result += "Hello, ";
which is same as:
result = result + "Hello, ";
This means: add "Hello, " to “result” and store the output in same variable. So there are two operations here – 1: Concatenation and 2: Assignment.
It will calculate the result of concatenation first, in a different memory location, and then output is copied to “result” variable. The calculation (concatenation) on RHS cannot be performed on same memory location on a variable in use, so a different temporary memory location would be required. Since we assume that String is mutable, same “result” variable can be used as opposed to creating a new one from scratch. But that temporary memory we used for calculation - what happens to that? We are not calling any method of String class that would manipulate its contents directly as opposed to the latter case of calling StringBuilder.Append() method. So even if String were mutable, we would have needed to call a method instead of simple concatenation and variable assignment to equate the performance.
The StringBuilder class reserves a buffer in the memory for the string it will work with. It keeps putting the contents we provide it in that buffer. When the buffer falls short, it doubles its size. So it doesn’t need to resize it each time. Finally when the ToString() method is called, the buffer is copied to a String variable and outputted. This helps it to perform better than String.
Since the StringBuilder class has the large overhead of initial object creation, it should only be used when we would be using it heavily (as in this case of 100000 concatenations). String doesn’t have this overhead. So if you use StringBuilder for a mere few concatenations, we will see a performance degrade instead of performance boost.
e.g. If we move the declarations inside the loop, the String would outperform StringBuilder, since now a new StringBuilder class needs to be created each time and it is not worth the number of concatenations we perform with it.
// Option 1:
for(int i = 0; i < 100000; i++)
{
string result = string.Empty;
result += "Hello, ";
result += "Hello, ";
}
// Option 2:
for(int i = 0; i < 100000; i++)
{
System.Text.StringBuilder result = new System.Text.StringBuilder();
result.Append("Hello, ");
result.Append("Hello, ");
}
You can keep adding result += "Hello, "; and result.Append("Hello, "); to see when StringBuilder starts performing better than String concatenation.