The Visual Basic String class isn't entirely different from the String type that programmers have used for years. The majority of string behaviors remain unchanged, and the majority of methods are now available as classes. However, to support the default behavior that people associate with the String primitive type, the String class isn't declared in the same way as several other classes. Strings in .NET do not allow editing of their data. When a portion of a string is changed or copied, the operating system allocates a new memory location and copies the resulting string to this new location. This ensures that when a string is copied to a second variable, the new variable references its own copy.
To support this behavior in .NET, the String class is defined as an immutable class. This means that each time a change is made to the data associated with a string, a new instance is created, and the original referenced memory is released for garbage collection. Note that garbage collection is the automated process of cleaning memory of data that is no longer needed. It is covered in more detail in Chapter 4. However, for now you should be aware that this is a comparatively expensive operation. However, having strings be immutable is important to ensure that the String class behaves as people expect a primitive type to behave. Additionally, when a copy of a string is made, the String class forces a new version of the data into the referenced memory. This ensures that each instance of a string references only its own memory. Consider the following code:
' String Concatenation vs String Builder
Dim strRedo = "A simple string"
For index = i To i0000 'Only i0000 times for concatenation strRedo &= "Making a much larger string"
' The date processing below uses the built in capability ' to subtract one datetime from another to get the difference ' between the dates as a timespan. This is then output as a ' number of milliseconds.
TextBoxl.Text &= "Time to concatenate strings: " &
(Now().Subtract(start)).TotalMilliseconds().ToString() & " String length: " & strRedo.Length.ToString() TextBoxl.Text &= line & Environment.NewLine
This code does not perform well. For each assignment operation on the strMyString variable, the system allocates a new memory buffer based on the size of the new string, and copies both the current value of strMyString and the new text that is to be appended. The system then frees the previous memory that must be reclaimed by the garbage collector. As this loop continues, the new memory allocation requires a larger chunk of memory. Therefore, operations such as this can take a long time.
To illustrate this, you'll note that the code captures the start time before doing the 10,000 concatenations, and then within the print statement uses the DateTime.Subtract method to get the difference. That difference is returned as an object of type Timespan, between the start time and the print time. This difference is then expressed in milliseconds (refer to Figure 2-8).
However, .NET offers an alternative in the System.Text.StringBuilder object, shown in the following snippet:
Dim strBuilder = New System.Text.StringBuilder("A simple string") For index = 1 To 1000000 '1 million times
strBuilder.Append("Making a much larger string")
TextBoxl.Text &= "Time to concatenate strings: " &
(Now().Subtract(start)).TotalMilliseconds().ToString() & " String length: " & strBuilder.ToString().Length.ToString() TextBoxl.Text &= line & Environment.NewLine End Sub
The preceding code works with strings but does not use the String class. The .NET class library contains the System.Text.StringBuilder class, which performs better when strings will be edited repeatedly. This class does not store strings in the conventional manner; it stores them as individual characters, with code in place to manage the ordering of those characters. Thus, editing or appending more characters does not involve allocating new memory for the entire string. Because the preceding code snippet does not need to reallocate the memory used for the entire string, each time another set of characters is appended it performs significantly faster.
Note that the same timing code is used in this snippet. However, for the StringBuilder, the loop executes one million times (versus ten thousand). Note the increase in the number of iterations was made in order to cause enough of a delay to actually show it requiring more than just one or two milliseconds to complete. Even with 100 times the number of iterations, Figure 2-8 still illustrates that this is a much more efficient use of system resources.
Ultimately, an instance of the String class is never explicitly needed, because the StringBuilder class implements the ToString method to roll up all of the characters into a string. While the concept of the StringBuilder class isn't new, because it is available as part of the Visual Basic implementation, developers no longer need to create their own string memory managers.
Was this article helpful?