AddThis Social Bookmark Button

Print

Efficient String Manipulations with StringBuilder

by Budi Kurniawan
07/15/2002

The System.String class is one of the most commonly used classes in .NET programming. It is immutable, however; once set, the content of a String object cannot be modified. Trying to change its value succeeds, but this actually destroys the old String object and creates a new one. String manipulation is not taboo though -- if you know the right class to use.

Prior to .NET, VB programmers were used to the String data type. It was easy to use, flexible, and often inevitable. Besides, there was no choice. When they upgraded to VB.NET, they found the same String data type wrapping the .NET Framework System.String class. It is still as easy to use, as flexible, and as important as the old String data type. However, there is now an alternative if you need to manipulate strings and avoid resource-hungry and time-consuming object creation. The alternative is somewhat hidden in the System.Text namespace: the StringBuilder class.

Constructing A StringBuilder Object

The System.Text.StringBuilder class is faster because it allocates an initial space when an instance of it is created. By default, a StringBuilder object created using the StringBuilder class' no-argument constructor reserves a space for 16 characters in memory. Therefore, if you later append more characters to it, as long as there is room for the new characters, no new StringBuilder needs to be created. The initial space depends on the implementation. This could be different in non-Windows implementation of the .NET Framework.

VB.NET Core Classes in a  Nutshell

Related Reading

VB.NET Core Classes in a Nutshell
By Budi Kurniawan, Ted Neward

The size of a StringBuilder object's storage can be obtained from the class' Capacity property. For example, the following code instantiates a StringBuilder object using the no-argument constructor and writes the capacity to the Console.


    Dim sb As New System.Text.StringBuilder()
    System.Console.WriteLine(sb.Capacity)   ' prints 16

You can change the capacity by assigning a different value to the Capacity property. The same capacity is also set aside if you construct an instance by passing a String object, such as the following.


    Dim sb As New System.Text.StringBuilder("Brainy")
    System.Console.WriteLine(sb.Capacity)   ' prints 16

However, if the string passed to the constructor exceeds 16 characters, the StringBuilder object will allocate enough space to accommodate all of the characters in the string. In this case, the initial capacity will be double the lower capacity. For example, the following code constructs a StringBuilder object by passing a string consisting of 20 characters. To accommodate the whole string, an initial capacity of 32 is allocated.


    Dim sb As New System.Text.StringBuilder(
         "12345678901234567890")
    System.Console.WriteLine(sb.Capacity)   ' prints 32

The next initial capacity, supposing you pass a string of 33 characters, will be 64 (2 x 32) and not 48 (3 x 16). The length of the string in a StringBuilder object can be obtained from its Length property. As an example, the following code prints both the capacity and the string length.


    Dim sb As New System.Text.StringBuilder(
         "12345678901234567890")
    System.Console.WriteLine(sb.Capacity)   ' prints 32
    System.Console.WriteLine(sb.Length)   ' prints 20

The capacity must be equal to or greater than the length. If you change the Capacity property value to a number less than the length of the internal string, a System.ArgumentOutOfRangeException will be thrown. However, if you append a string to a StringBuilder object and the operation results in a string whose length exceeds the StringBuilder object's capacity, the capacity will be increased automatically. Be warned, though: the key to getting the most benefit from the StringBuilder class is to make sure that the length of the string it contains is always less than the capacity. In other words, the performance will degrade if a StringBuilder object has to allocate more memory to increase its capacity. To ensure you can assign a big enough initial capacity, the StringBuilder class provides another constructor that accepts an integer. This integer will be the initial capacity for the StringBuilder object.


Public Sub New (ByVal capacity As Integer)

If you want to instantiate a StringBuilder object by passing a String, but want to define your own initial capacity, use the constructor that accepts a String and an integer.


Public Sub New (ByVal value As String, 
     ByVal capacity As Integer)

The StringBuilder class also allows you to specify the maximum capacity that an instance can grow to, using the following constructor.


Public Sub New (ByVal capacity As Integer, 
     ByVal maxCapacity As Integer)

The maximum capacity can be obtained from the MaxCapacity property. If you construct a StringBuilder object without specifying a maximum capacity, the default will be the same as Int32.MaxValue. Like the Capacity property, the default value of MaxCapacity is implementation-dependent. Now, let's have a look at other features that come with the StringBuilder class.

Accessing Individual Characters

Like the System.String class, the StringBuilder class allows you to access each individual character of its internal string by using the Chars property. For example, the following code constructs a StringBuilder object by passing the string "brainy," and then prints the first character of the string.


    Dim sb As New System.Text.StringBuilder("brainy")
    System.Console.WriteLine(sb.Chars(0))   ' prints b

The Chars property of the StringBuilder class is more flexible than the same property in the String class, because in StringBuilder the Chars property is read-write, whereas the String class' Chars property is read-only. This makes StringBuilder objects very flexible, because you can also write to individual characters. Consider the following example.


    Dim sb As New System.Text.StringBuilder("dingdong")
    sb.Chars(0) = "p"c
    sb.Chars(4) = "p"c
    System.Console.WriteLine(sb)   ' prints pingpong
    sb.Chars(0) = "k"c
    sb.Chars(4) = "k"c
    System.Console.WriteLine(sb)   ' prints kingpong

Appending A Value

You use the Append method to append a value to the existing string. This method has 19 overloads to make sure you can append values in any format. Therefore, you can append a string, a byte, an integer, a long, an Object, a Single, a Double, and array of characters, and so on. For example, the following snippet appends a string and an integer to a StringBuilder object.


    Dim sb As New System.Text.StringBuilder()
    Dim text As String = "Total product(s): "
    Dim count As Integer = 19
    sb.Append(text).Append(count)
    System.Console.WriteLine(sb)   
    ' prints Total product(s): 19

Inserting A Value

To insert a new value to an existing StringBuilder object, you use the Insert method. This method has 18 overloads that accept a value of any format. Each overload accepts two or more arguments, the first being the index indicating the insertion point. For example, here is the signature of the Insert method overload with which you can append an integer.


Overloads Public Function Insert( _
  ByVal index As Integer, _
  ByVal value As Integer) _
  As StringBuilder

Note that the Insert method returns a StringBuilder object that is the reference to the same instance. For example, the following code constructs a StringBuilder object with an initial string value and then inserts a new string at index 0.


    Dim sb As New System.Text.StringBuilder("
         product(s): 19")
    sb.Insert(0, "Total ")
    System.Console.WriteLine(sb)   
    ' prints Total product(s): 19

Removing A Substring

You can remove a range of characters from a StringBuilder object using the Remove method. The signature of this method is as follows.


Public Function Remove( _
  ByVal startIndex As Integer, _
  ByVal length As Integer)
  As StringBuilder

Where startIndex is the start index at which the removal begins, and length is the number of characters to be removed. For example, the following code removes the "or" from "War and or Peace."


    Dim sb As New System.Text.StringBuilder("
         War and or Peace")
    sb.Remove(8, 3)
    System.Console.WriteLine(sb)   
    ' prints War and Peace

Replacing Characters and Substrings

You can replace an individual character in a StringBuilder object with another character or a substring with another substring using the Replace method. In particular, you use one of the following overloads.


Overloads Public Function Replace( _
  ByVal oldChar As Char, _
  ByVal newChar As Char ) _
  As StringBuilder 

Overloads Public Function Replace( _
  ByVal oldValue As String, _
  ByVal newValue As String ) _
  As StringBuilder 

For example, in the following code you replace all occurrences of "d" with "k."


    Dim sb As New System.Text.StringBuilder("dingdong")
    sb.Replace("d"c, "k"c)
    System.Console.WriteLine(sb)   ' prints kingkong

As another example, the following replaces the word "and" with "or."


    Dim sb As New System.Text.StringBuilder("table and 
         chair and wheelchair")
    sb.Replace("and", "or")
    System.Console.WriteLine(sb)   ' prints table or 
         chair or wheelchair

The other two overloads of the Replace method enable you to specify a range of positions of characters to be replaced. The signatures are as follows.


Overloads Public Function Replace( _
  ByVal oldChar As Char, _
  ByVal newChar As Char, _
  ByVal startIndex As Integer, _
  ByVal count As Integer ) _
  As StringBuilder 

Overloads Public Function Replace( _
  ByVal oldValue As String, _
  ByVal newValue As String, _
  ByVal startIndex As Integer, _
  ByVal count As Integer ) _
  As StringBuilder 

For example, the following code replaces the first "d" in "dingdong" but not the second "d."


    Dim sb As New System.Text.StringBuilder("dingdong")
    sb.Replace("d"c, "k"c, 0, 2)
    System.Console.WriteLine(sb)   ' prints kingdong

As another example, the following example replaces the first "and" but not the second one.


    Dim sb As New System.Text.StringBuilder("table and 
         chair and wheelchair")
    sb.Replace("and", "or", 0, 10)
    System.Console.WriteLine(sb)   ' prints table or 
         chair and wheelchair

Converting Into String

A multiplicity of methods in various .NET classes expect a String object as an argument. Therefore, it is important to convert a StringBuilder object into a String object before you pass it to one of those methods. The StringBuilder class provides you with the ToString method. Using this method is very simple. For instance, here is the code that converts a StringBuilder object into a String.


    Dim sb As New System.Text.StringBuilder("Total 
        product(s): 19")
    System.Console.WriteLine(sb.ToString())   
         ' prints Total product(s): 19

Budi Kurniawan is a senior J2EE architect and author.


Return to .NET DevCenter