From time to time I read on various channels that you should always use a StringBuilder
because it is faster and uses fewer allocations. If you read the term always then you should be even more careful.
In this blog post, I want to show you that this is not true and what alternatives are (even faster than the StringBuilder
).
Why StringBuilder
in the first place?
Let's discuss what the StringBuilder
tries to solve. As I already discussed a while back I will quote myself here:
Why concatenating strings is slow and takes a lot of allocations. The sole reason is immutability. strings are immutable. That means if you want to change a string or append another to our string you have to create a new one. This is a conscious design decision of the C# team. Other languages like Swift or C/C++ have mutable strings! Java has immutable strings as well!
Taken from: Create a low allocation and faster StringBuilder - Span in Action
Benchmark
Let's make the test: We compare a normal +
against the StringBuilder
:
[Benchmark]
public string StringBuilder()
{
var builder = new StringBuilder();
for (var i = 0; i < Iterations; i++)
builder.Append(TextToAppend);
return builder.ToString();
}
[Benchmark]
public string Concat()
{
var output = string.Empty;
for (var i = 0; i < Iterations; i++)
output += TextToAppend;
return output;
}
And here are the results:
We can see that for lots of operations the StringBuilder
outperforms the +
operator (also string.Concat
for that matter). But we can also see for a very small amount of concatenations the picture shifts. Concat
uses fewer allocations and is faster. So I guess we debunked the always part. But we can take this even further:
Use List<string>
Often times a simple list of strings can be easier and faster. A full-blown StringBuilder
does more than append some strings. You can also remove parts of the string or insert them somewhere in the middle. If you don't need this, a List<string>
can be equally powerful or even faster.
Benchmark]
public string ListOfStrings()
{
var list = new List<string>();
for(var i = 0; i < Iterations;i++)
list.Add(TextToAppend);
return string.Join(string.Empty, list);
}
The result:
We can see, that the list often can outperform the StringBuilder
. And guess what the .NET team uses List<string>
instead of a StringBuilder
(for example in Blazor).
Conclusion
The world is mostly grey and not black and white. So check for your situation what fits best. Yes, StringBuilder
can be faster but also brings more complexity with it. For small amounts, an easy concat will do the trick or you just use a simple List<string>
.