"Use always a StringBuilder" - Internet myths

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: Concat vs Builder

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: List vs Builder

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>.

Resources

  • Source code to this blog post: here
  • All my sample code is hosted in this repository: here

Create a low allocation and faster StringBuilder - Span in Action

.NET ships a nice StringBuilder since the dawn of time or at least since the beginning of the framework itself. The intention is simple: If we need to concatenate a lot of strings we can't rely on the + operator as we introduce a lot of unnecessary allocations plus it is slow! That is where the StringBuilder jumps into the picture.

Why is that? Why is the StringBuilder better? And can we do better? Spoiler: Yes!

How to enumerate through a StringBuilder

Did you ever wonder how we can iterate through a StringBuilder? I mean, of course, we can just call ToString and use the returned string, but that means we materialize the whole thing without good reason.

We can also use a normal for-loop. But we can also find a completely different and probably dumber way! And if you wonder: No, this is not something you do in your daily life, but by doing so, I can show some cool stuff C# and .NET offer.

StringBuilders magic for very large strings

The StringBuilder class is used to create mutable sequences of characters. Strings are immutable, so if you need to perform multiple operations on a string, it is better to use a StringBuilder instead of a string. This is especially useful when you need to concatenate a large number of strings. But there is more magic to it, especially when we go BIG!

An error has occurred. This application may no longer respond until reloaded. Reload x