(Print this page)

Strings, Strings, Strings
Published date: Tuesday, August 1, 2006
On: Moer and Éric Moreau's web site

Imagine for a minute that you are lying on a beach and all you see around you are beautiful young women wearing strings. You turn your head in the other direction and you see me, wearing a … No! Forget that horrible picture and stop dreaming. I won’t talk of haute couture; I will talk about 3 kinds of strings you find in the .Net Framework 2.0. These 3 classes are the String class, the StringBuilder class and the new SecureString class.

I don’t want to spend your precious time enumerating all properties and methods of these classes. Just a couple of reminders and differences and I will spent more time in the new SecureString class. I will also warn you about performance consideration.

The String class

The String class is part of the System namespace. You surely have used strings since the first day you started programming so I won’t spend much time on this. There are many properties and methods (and many overloads on these methods) to cover them all here. Also, the help file is a great resource for these.

If you are accustomed to the fixed-length strings of VB6 (Dim s As String * 10), this feature does not exist anymore unless you are ready to use the Microsoft.VisualBasic.Compatibility namespace (you also need to add a reference to it before being able to use it). If you are able to avoid it, please do. Notice that you need to pass through the Value property to read/write the content of this variable. Here is an example:

Dim fls2 As New Compatibility.VB6.FixedLengthString(15)
fls2.Value = "aa"
MessageBox.Show(">>" & fls2.Value & _
        "<< has a lenght of " & fls2.Value.Length)
If you find the VBFixedString attribute in your reading, be advised that it doesn’t have the same purpose (even if the name sounds familiar). It is design to be used with operations such as FileGet and FilePut.

Strings are immutable

In .Net (since the first version), a String object is immutable. That means that once a string has been created, its content can never change. When you call a method of the string class or when you append characters to an existing string, you are in fact creating a new string in memory (and the first one is disposed).

A very common mistake I see is that people says there calling a function on a string but the function does not work. For example, if you have these lines of code, the value of the variable “s” displayed in the message box is still “abcdef” because the original string is immutable:

Dim s As String = "abcdef"
s.Replace("cd", "yz")
The correct syntax requires that you store the results into a variable (the same if you want but you now know that a new one will be created in memory for you):
s = s.Replace("cd", "yz")

The StringBuilder class

This class is part of the System.Text namespace.

A StringBuilder object is a kind of buffer that is set to a size (16 characters by default) and that buffer does not need to be disposed and recreated (like a normal string) when its content change until it exceeds its capacity.

The version 2.0 of the .Net Framework has added a very powerful method to the StringBuilder class: the AppendLine method. Ok, it is not powerful but at very least useful! I often found myself adding “Environment.NewLine” to each of my line. I can now call this new method. This new method simply adds the default line terminator to the StringBuilder object.

A note on performance

I normally don’t like performance tests when these tests are nothing more then a big loop. But what else to give you an idea of the impact of the String compared to the StringBuilder?

This immutable aspect of the strings has an impact on performance when you constantly need to change the value of a string. When compared to StringBuilders, concatenation of strings is about 100 times slower.

In the downloadable demo application, there is a button for that. Initially, the loop will be executed 10,000 times. If you put a significant greater value you will have plenty to get a coffee. If you only want to test the StringBuilder, I suggest that you comment out the first loop.

Figure 1: See the difference

Even the StringBuilder can be optimized (but it makes sense only if you are dealing with very large loops). To test it out, comment out the first loop (the regular String) and pump up the intLimit variable to 1,000,000. You will discover that calling the Append method twice (sb2) is faster then concatenating the string before appending (sb1). You will also discover that the AppendLine method (sb3) has no performance cost (it is in fact very slightly faster the sb2).

Here are some of the test lines:

'Test 2 : Use the Append method of the StringBuilder
Dim sb1 As New System.Text.StringBuilder
For i = 1 To intLimit
    sb1.Append(i.ToString & Environment.NewLine)

'Test 3 : Use 2 Append method of the StringBuilder
Dim sb2 As New System.Text.StringBuilder
For i = 1 To intLimit

'Test 4 : Use the AppendLine method of the StringBuilder
Dim sb3 As New System.Text.StringBuilder
For i = 1 To intLimit
But don’t forget, this is only a pure performance test. The main point you have to agree is that the StringBuilder is faster then the String when you need to append text in many chunks. When it comes to the StringBuilder, I would definitely go with the AppendLine method when I need the line terminator because of the readability of the code (and also because I am too lazy to concatenate the Environment.NewLine value).

The SecureString class

This new class is part of the System.Security namespace.

Some people were concerned that strings are stored in memory “in clear text”. Some people are handling sensitive data and don’t like the idea that other process can spy the memory to find their data. In the .Net Framework 2.0, a new class is available to protect sensitive data.

The text value stored in a variable of type SecureString is automatically encrypted. In fact, a SecureString variable is an array of characters that is encrypted using the Data Protection API (DPAPI). You can only work with variables of this type on a character basis. You cannot pass a string to it and there is no way of getting its value in clear text.

So how do we use a variable of that kind? If you look at the list of the members of this class, it is quite short but exposes the following methods: AppendChar, InsertAt, SetAt, and RemoveAt. These 4 methods give you everything you need to modify the value. If you look again at the list of members, you will find the ToString method. Haven’t I said that there was no way of easily reading from it? This method simply returns the type name of the object which is System.Security.SecureString. To be able to read it, you need to use some interops like this (for these lines to work, you need to import System.Runtime.InteropServices):

Dim ptr As IntPtr = Marshal.SecureStringToBSTR(strSecure)
MessageBox.Show("The secret is: " & Marshal.PtrToStringBSTR(ptr))
One interesting method of this class is called MakeReadOnly. After you called this method, you cannot use the AppendChar, InsertAt, SetAt, and Remove at methods (otherwise it raises an InvalidOperationException). Be careful before executing this method, you cannot revert back to a writable SecureString.

There are some serious limitations to this class that you should be aware:

  • SecureString variables are not serializable.
  • SecureString variables are not visible to COM (there is no way for a legacy VB6 application to read the value).
  • SecureString variables are only supported on Windows 2000 service pack 3 and later (not on Windows 98 or ME).

I am not a 100% sure but I think that (for now) the only real place where an instance of a SecureString class can be passed as is and is recognize correctly is to the Password property of a ProcessStartInfo class instance.


Now you know that the StringBuilder is faster then the String when comes time to append many block of text. You are also aware of the new SecureString class (let’s just hope that future version of the .Net Framework will widen its use).

I hope you appreciated the topic and see you next month.

(Print this page)