Getting developers to use the StringBuilder class can be a hard sell because when viewed one instance at a time, string concatenation doesn't seem like a big deal. When you multiply it by hundreds or thousands of operations, though, it's suddenly very obvious that string concatenation is slow.
Strings are immutable, which means they can't be changed. So to arrive at a concatenated string, we need to create a new string based on the combination of two other strings. Imagine creating a long string in your own custom server control, having to create a new object with every additional line you added to the string. Each time you concatenate, a new object is created, and the contents of two other string objects must be copied over to the new object.
StringBuilder works differently by creating an expandable buffer in memory. By using its Append() method, and its ToString() method when you're done, you avoid all of that memory copying and object creation. The easiest way to demonstrate its efficiency compared to plain string concatenation is with a little code. Listing 15.2 shows the sample. The trace output on the page yields the results shown in Table 15.1.
C#
using System; using System.Text; using System.Web; public partial class StringBuild_aspx { void Page_Load(object sender, EventArgs e) { string sentence = "I really like riding roller coasters because they're super fun andhave ups and downs, just like life!"; string[] words = sentence.Split(new char[] { ' ' }); string result = "; Trace.Warn("Start concatenation"); for (int i = 0; i < 1000; i++) { foreach (string word in words) { result = result + word + " "; } } Trace.Warn("End concatenation"); Trace.Warn("Start StringBuilder"); StringBuilder builder = new StringBuilder(); for (int i = 0; i < 1000; i++) { foreach (string word in words) { builder.Append(word); builder.Append(" "); } } result = builder.ToString(); Trace.Warn("End StringBuilder"); } }
VB.NET
Imports System Imports System.Text Imports System.Web Public Partial Class StringBuild_aspx Sub Page_Load(sender As Object, e As EventArgs) Dim sentence As String = "I really like riding roller coasters because they're superfun and have ups and downs, just like life!" Dim words As String() = sentence.Split(New Char() {" "c}) Dim result As String = " Trace.Warn("Start concatenation") Dim i As Integer For i = 0 To 999 Dim word As String For Each word In words result = result + word + " " Next word Next i Trace.Warn("End concatenation") Trace.Warn("Start StringBuilder") Dim builder As New StringBuilder() Dim i As Integer For i = 0 To 999 Dim word As String For Each word In words builder.Append(word) builder.Append(" ") Next word Next i result = builder.ToString() Trace.Warn("End StringBuilder") End Sub End Class
Message | From Last |
---|---|
Start concatenation | 0.000157 |
End concatenation | 22.377516 |
Start StringBuilder | 0.000212 |
End StringBuilder | 0.013082 |
The code first splits up a sentence into a string array of words, using the Split() method to divide the sentence by its spaces. Next, it concatenates a string by recombining the words with spaces in between them, repeating this action a thousand times. The same task is then repeated using a StringBuilder object. Messages are sent to the page's trace output, marking the start and end times of each action.
Although it's pretty ridiculous to think that you would ever concatenate a couple words a thousand times over, this exercise does demonstrate how string concatenation doesn't scale well. It took more than 22 seconds to do the straight concatenation, compared to a little over a hundredth of a second to accomplish the same thing with StringBuilder. On a smaller scale, the difference might not be as huge, but when thousands of users are hitting your site and this kind of concatenation must occur, which method would you rather use?