Олег Михайлик и Гайдар затеяли разбирательство на тему того, почему String.Empty и "" равны или не равны друг другу.
Подробные объяснения от Олега можно прочесть тут: http://blogs.gotdotnet.ru/personal/mihailik/CommentView.aspx?guid=2F1AF381-0EF6-4F8E-97F9-28CFB9F2162B
Добавить хотелось только то, что у Рихтера есть и вторая книжка (так и вспоминается КВН: "букварь, вторая и синяя" :)).
Так вот в ней описано как интернирование строк в .NET Framework 2.0 и атрибут CompilationRelaxions, так и то, почему не стоит ему доверять.
Я просто процитирую:
Если сборка отмечена атрибутом CompilationRelaxions, определяющим значение флага CompilationRelaxions.NoStringInterning, в соответствии со спецификацией ECMA CLR может не интернировать все строки, определенные в метаданных сборки. Заметье: в целях повышения производительности приложения компилятор C# всегда при компиляции сборки определяет этот атрибут/флаг.
Даже если в сборке определен этот атрибут/флаг, CLR может предпочесть интернировать строки.
[SKIP, здесь идет код, который показывает, что строки и не должны бы интернироваться, но все равно это происходит]
Причина в том, что эта версия CLR предпочитает игнорировать атрибут/флаг, созданный компилятором C#, и CLR интернирует строку при загрузке в AppDomain.
[SKIP]
В действительности, CLR версии 2.0 учитывает этот атрибут/флаг, но только если код сборки создан с использованием утилиты NGen.exe
Вот такие вот пироги, вот и объяснение того, почему константа String.Empty в mscorlib не интернирована.
Даже если задать атрибут для своей сборки руками, не полагаясь на компилятор, то результат получится тот же самый, я как-то проверял.
Так что тот же самый Рихтер прав: не стоит закладываться на то, интернированы ли строки, или нет. С другой стороны, мало кто, думаю, пользуется сравнением строк через ReferenceEquals :)