И еще: буквенные строки (строки, объявленные в исходном коде) по умолчанию интернированы в пул для экономии памяти.
string s1 = "MyTest";
string s2 = new StringBuilder().Append("My").Append("Test").ToString();
string s3 = String.Intern(s2);
Console.WriteLine((Object)s2==(Object)s1); // Different references.
Console.WriteLine((Object)s3==(Object)s1); // The same reference.
Несмотря на то, что он экономит память, когда одна и та же буквальная строка используется несколько раз, поддержка пула обходится в несколько процессоров, и как только строка помещается в пул, она остается там до остановки процесса.
Используя CompilationRelaxationsAttribute , вы можете сказать JIT-компилятору, что вы действительно не хотите, чтобы он интернировал все литеральные строки.
[assembly: CompilationRelaxations(CompilationRelaxations.NoStringInterning)]