The StringBuilder Class

Learn how to efficiently manipulate text and manage memory using the mutable StringBuilder class.

The System.String class offers many methods for handling text. A new string is created any time we make a change to a string object because strings are immutable. This immutability becomes a problem if our program handles large texts and makes many modifications. Memory allocation is a costly operation in terms of both memory and processing power.

To solve this, .NET provides the StringBuilder class. This class acts as a mutable version of System.String.

Using StringBuilder

Mutability is achieved by allocating more memory space than is currently required. The capacity and length properties measure different aspects of the object.

Note: The StringBuilder class is located in the System.Text namespace.

StringBuilder length and capacity

We can inspect the properties of the object to see how memory is reserved.

C# 14.0
using System.Text;
var stringBuilder = new StringBuilder("Hello World!");
Console.WriteLine($"Length of the string stored inside: {stringBuilder.Length}.");
Console.WriteLine($"Current total capacity: {stringBuilder.Capacity}.");
  • Line 1: We include the System.Text namespace to access the StringBuilder class.

  • Line 3: We instantiate a new StringBuilder object with an initial string.

  • Lines 4–5: We output both the current character count and the total allocated memory capacity.

The string "Hello World!" is 12 characters long, but the StringBuilder allocates space for 16 characters by default.

This capacity is doubled whenever the length of the string reaches the current capacity. We can see this expansion by appending more text.

Appending to the StringBuilder object

We use the Append method to modify the text in place.

C# 14.0
using System.Text;
var stringBuilder = new StringBuilder("Hello World!");
Console.WriteLine($"Length of the string stored inside: {stringBuilder.Length}.");
Console.WriteLine($"Current total capacity: {stringBuilder.Capacity}.");
Console.WriteLine("Appending to the StringBuilder object...");
stringBuilder.Append(" Hello once again!");
Console.WriteLine($"New length: {stringBuilder.Length}.");
Console.WriteLine($"New total capacity: {stringBuilder.Capacity}.");
  • Line 3: We create the initial StringBuilder object.

  • Line 8: We use the Append method to add text to the existing object without creating a new instance.

  • Lines 9–10: We observe the updated length and the newly doubled capacity.

After appending to the StringBuilder object, the new length is 30 characters. Because this new length is less than 32, the capacity doubled. If the new length were more than double the current capacity, the new capacity would exactly equal the new length.

We can push the length past the doubled capacity threshold.

C# 14.0
using System.Text;
var stringBuilder = new StringBuilder("Hello World!");
Console.WriteLine($"Length of the string stored inside: {stringBuilder.Length}.");
Console.WriteLine($"Current total capacity: {stringBuilder.Capacity}.");
Console.WriteLine("Appending to the StringBuilder object...");
stringBuilder.Append(" Hello once again!!!!!");
Console.WriteLine($"New length: {stringBuilder.Length}.");
Console.WriteLine($"New total capacity: {stringBuilder.Capacity}.");
  • Line 8: We append a string large enough to push the total length past the standard doubled capacity boundary.

  • Lines 9–10: We verify that the capacity and length now match exactly.

Notice that the capacity and the length are now both 34. Memory allocation does happen, but it does not occur every time the contents of the StringBuilder object change. Memory is only allocated when the current capacity is full.

Note: If we know that we will append to the StringBuilder object many times, we can estimate how much memory we need and provide this number to the constructor. This approach avoids constant memory allocation.

The StringBuilder methods

The StringBuilder class does not have the same variety of methods as System.String. However, the class does provide enough functionality to effectively work with textual information:

  • The Insert() method inserts a given substring to a certain position.

  • The Append() method appends a substring to the end of the StringBuilder object.

  • The AppendLine() method does the same thing but also inserts a line break at the end.

  • The Replace() method replaces all occurrences of a given character or substring with another character or substring.

  • The Remove() method removes a certain number of characters, starting with a given index.

We can use these methods together to manipulate a block of text.

C# 14.0
using System.Text;
var document = new StringBuilder("Starting text.");
Console.WriteLine(document.ToString());
// Append adds to the end
document.Append(" More text.");
document.AppendLine(" End of line 1.");
Console.WriteLine(document.ToString());
// Insert adds at a specific index
document.Insert(0, "Title: ");
Console.WriteLine(document.ToString());
// Replace swaps specific characters or words
document.Replace("text", "data");
Console.WriteLine(document.ToString());
// Remove deletes a specified number of characters starting at an index
document.Remove(0, 7);
Console.WriteLine(document.ToString());
  • Line 3: We create the initial object with base text.

  • Line 4: We print the initial state of the document.

  • Lines 7–8: We add content to the end, including a line break using AppendLine.

  • Line 9: We print the document to see the appended text.

  • Line 12: We place the word “Title: ” at the very beginning (index 0).

  • Line 13: We print the document to observe the insertion.

  • Line 16: We locate all instances of “text” and swap them with “data” entirely in place.

  • Line 17: We print the document to verify the replacements.

  • Line 20: We delete 7 characters starting from index 0, effectively removing the “Title: ” prefix we just added.

  • Line 21: We convert the final StringBuilder object back into a standard string and print it.

Note: Remember that a StringBuilder object is not an instance or child of System.String. We must use the ToString() method to extract the standard string stored inside.