In this article, we are going to talk about StringBuilder in C#.

To download the source code for this article, you can visit our GitHub repository.

Let’s dive in.

What is StringBuilder in C#?

The string type is immutable in C#, so we cannot change its content after its creation. This means that if we create a string type object and try to amend it, it will create a new instance of the object in the memory. And if we alter the string a lot of times, it can cause some performance problems.

StringBuilder solves this problem, because, unlike string, it can dynamically expand its memory to support any manipulation of its contents. In the illustration below, we can see how they both allocate memory:

stringbuilder string memory allocation

 

On one hand, when we alter a string type, the framework will allocate another memory space, as depicted in the diagram. On the other hand, we can see that a StringBuilder uses a single memory allocation for all its string manipulation. A StringBuilder maximum capacity is Int32.MaxValue, while the default value is 16 characters. It has a capacity property that maintains the value. The StringBuilder length property keeps the number of the current capacity of the StringBuilderĀ and this value increases when we add more characters.

While adding characters to StringBuilder, if the number of added characters exceeds the current capacity, the capacity property will be doubled, and the length property adjusted appropriately. This process is recursive, although trying to add additional characters or expand it beyond its maximum capacity throws an OutOfMemoryException exception.

How to Instantiate a StringBuilder

Instantiating a StringBuilder is pretty straightforward. We can instantiate it by using the new keyword for creating an object of a class. Also, a StringBuilder has different constructors:

public void Instantiate()
{
    var value = "How to instantiate a StringBuilder";
    var index = value.IndexOf("H") + 7;
    var capacity = 30;
    var maxCapacity = 100;

    // Instantiate a StringBuilder 
    var sb = new StringBuilder();

    // Instantiate a StringBuilder and define a capacity
    sb = new StringBuilder(capacity);

    // Instantiate a StringBuilder and define a capacity and maximum capacity
    sb = new StringBuilder(capacity, maxCapacity);

    // Instantiate a StringBuilder from a string.
    sb = new StringBuilder(value);

    // Instantiate a StringBuilder from string  with a default capacity.  
    sb = new StringBuilder(value, capacity);

    // Instantiate a StringBuilder from substring and define a capacity.  
    sb = new StringBuilder(value, index, value.Length - index, capacity);
}

Convert StringBuilder to String

We can use a StringBuilder for any form of string manipulation. But, the StringBuilder does not return a string. Hence, to retrieve a string, we must use the ToString() method:

var stringBuilder = new StringBuilder("Adding Text to a StringBuilder.");
var stringOutcome = stringBuilder.ToString();

First, we create StringBuilder with a default text and then convert the content to a string.

StringBuilder Methods

There are some methods we can use to manipulate the contents of a StringBuilder. They are Append(), AppendLine(), AppendFormat(), Replace(), Insert(), Clean() and Remove().

Append

The Append() method adds a new string to the end of the current StringBuilder. It can double the length of the StringBuilder, and space allocation is automatic:

var stringBuilder = new StringBuilder("Welcome, ");
stringBuilder.Append("IĀ hopeĀ youĀ learnedĀ something.");

As we can see, we use the Append method to add some text to the StringBuilder.

As a result, we get:

Welcome, I hope you learned something.

AppendLine

When we want to add a line terminator to our StringBuilder, AppendLine() comes to the rescue. We can do this by creating aĀ StringBuilder and applying the method:

var stringBuilder = new StringBuilder("Welcome, IĀ hopeĀ youĀ learnedĀ something."); 
stringBuilder.AppendLine();

AppendFormat

AppendFormat() adds a string in a defined format to the end of StringBuilder. The resulting string reveals the conventions of the current system culture or a specified culture. The method allows us to pass as input the format we want for our string:

var stringBuilder = new StringBuilder("Welcome, ");
stringBuilder.AppendFormat("to register for the full class, you need to pay a sum of {0:C}", 157);

Now we get a nicely formatted string:

Welcome, to register for the full class, you need to pay a sum of $157.00

Insert

We use this method to add a string, substring, a character array, a portion of a character array, or the string representation of a primitive data type at a specified position in our StringBuilder object. The method also allows us to include the index for our insertion:

var stringBuilder = new StringBuilder("Hi");
stringBuilder.Insert(2, ", welcome to our blog");

Replace

This method replaces the occurrences of some characters in the StringBuilder object. The method takes as input the sequence of characters that we want to replace and a new value:

var stringBuilder = new StringBuilder("Welcome, I hope you learned something");
stringBuilder.Replace("learned", "gained");

Remove

The Remove() method eliminates a specified number of characters from the StringBuilder. The input parameters are the start index and the number of characters to delete:

var stringBuilder = new StringBuilder("Welcome, IĀ hopeĀ youĀ learnedĀ something today");
stringBuilder.Remove(0,8);

The Remove method starts from index 0 and removes 8 characters.Ā 

ClearĀ 

This method removes all characters from the StringBuilder object. When we use this method on a StringBuilder, the length becomes zero:

var stringBuilder = new StringBuilder("Welcome, IĀ hopeĀ youĀ learnedĀ something");
stringBuilder.Clear();

StringBuilder Performance

For us to understand the difference in string and StringBuilder performance, we are going to compare some actions performed on both of them and their execution time and memory consumption:

|                   Method |      Mean | Allocated |
|------------------------- |----------:|----------:|
|  AppendWithStringBuilder |  38.05 Ī¼s |     40 KB |
|         AppendWithString | 411.68 Ī¼s |  2,791 KB |
|  InsertWithStringBuilder | 116.05 Ī¼s |    100 KB |
|         InsertWithString | 179.68 Ī¼s |  1,004 KB |
|  RemoveWithStringBuilder |  90.62 Ī¼s |     12 KB |
|         RemoveWithString | 139.29 Ī¼s |    382 KB |
| ReplaceWithStringBuilder | 571.77 Ī¼s |     12 KB |
|        ReplaceWithString | 106.71 Ī¼s |    137 KB |

We can see from the test output that most of the methods performed faster with StringBuilder, while some did not (the Replace() method). Performance depends on other factors as well, like memory consumption, the type of operation, the system we’re running the code on, etc.

Also, it’s obvious that StringBuilder consumes less memory space in each case.

When Should We Use StringBuilder?

We should use the StringBuilder class when:

  • We expect a lot of operations on a string
  • We need to perform a lot of search operations (StringBuilder doesn’t have the Contains(), IndexOf(), or StartsWith() methods)
  • There’s an indefinite number of operations (e.g., using a while loop)

On the other hand, if we have to perform a few operations or a fixed number of operations on a string literal, we’ll be better off using the plain old String class.

Conclusion

In this article, we have learned about StringBuilder in C# and how it works. We have also covered some methods that can be used to manipulate the contents of a StringBuilder.Ā