In this article, we are going to talk about StringBuilder in C#.
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:
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()
, orStartsWith()
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.