The sample code in this post demonstrates that the run time maintains a string intern pool. The intern pool allows sharing of string instances. Interning is primarily a memory optimization, but can also be a performance optimization in some unique scenarios.
The runtime will store strings literals in the intern pool. For example:
using System;
class Class1
{
[STAThread]
static void Main(string[] args)
{
string s1 = "bbb";
string s2 = "bbb";
Console.WriteLine("{0},{1}", s1, s2);
}
}
If you look at the IL code for the above program, you might be tempted to think we are dealing with two different string instances. In other words, s1 and s2 will point to different string objects.
IL_0000: ldstr "bbb"
IL_0005: stloc.0
IL_0006: ldstr "bbb"
IL_000b: stloc.1
This is not the case, as the following program will demonstrate.
using System;
class Class1
{
[STAThread]
static void Main(string[] args)
{
string s1 = "bbbbbb";
string s2 = "bbbbbb";
// this expression returns true
// both string variables reference the
// same interned string
bool b = Object.ReferenceEquals(s1, s2);
Console.WriteLine(b);
// create a new string with the same value
// as the above: "bbbbbb"
string s3 = new string('b', 6);
// this expression returns false
// even though s3 references "bbbbbb",
// it's not the same string instance
// referenced by s1,s2
b = Object.ReferenceEquals(s1, s3);
Console.WriteLine(b);
// See if "bbbbbb" is already interned by
// checking the reference returned by Intern
string s4 = String.Intern(s3);
// this expression returns true
// s4 is pointing to the same object as s1,s2
b = Object.ReferenceEquals(s1, s4);
Console.WriteLine(b);
}
}