System.String is one of the few classes in the .NET Framework Base Class Library that is given special treatment by the CLR. Although it is a reference type (it derives from System.Object and not System.ValueType), it behaves much like a value type at runtime.
String copy and compare operations result in value semantics rather than reference semantics.
Have a look at this code
string str1 = "I am str1"; string str2 = str1; str1 = "I have changed now!"; System.Console.WriteLine(str2);
This code prints “I am str1”. It shows that the second line of code resulted in assignment of value and not reference. Does it mean that a new string was created during assignment? No. To make things more confusing, the same string was assigned to both variables.
The CLR optimizes string management by maintaining an internal pool of string values known as an intern pool for each .NET application. If the value being assigned to a string variable is the same as one of the strings already in the intern pool, no new string is created and the variable points to the address of the string in the pool. The compiler is capable of using the intern pool to optimize string initialization and have two string variables pointing to the same String object in memory. This optimization step is done only at compile time and isn’t performed at run time, though, because the search in the pool takes time and can even fail, adding overhead to the application.
//No optimization is done at run time. string str1 = "ABC"; str1 += "XYZ"; string str2 = "ABCXYZ"; //These two variables point to different String objects. Console.WriteLine(string.ReferenceEquals(str1, str2)); //False
String management can be optimized by using the String.Intern static method. This method searches a string value in the intern pool and returns a reference to the pool element that contains the value if the value is already in the pool. If the search fails, the string is added to the pool and a reference to it is returned. Notice how you can “manually” optimize the preceding code snippet by using the String.Intern method:
string str1 = "ABC"; str1 += "XYZ"; //Move S1 to the intern pool. str1 = String.Intern(str1); //Assign S2 a string that is already in the pool). string str2 = "ABCXYZ"; //These two variables point to the same String object. Console.WriteLine(string.ReferenceEquals(str1, str2)); //True
This optimization technique makes sense only if you’re working with long strings that appear in multiple portions of the applications. Using the Intern method, you can help your application produce a smaller memory footprint. You can also use the IsInterned static method to check whether a string is in the intern pool (in which case the string itself is returned) or not (in which case the method returns Nothing):
if (string.IsInterned(str1)) { //str1 is already in the intern pool. } else { //str1 is not in the intern pool. }