Ответ
Интернирование строк — это механизм CLR, который хранит в памяти (string intern pool) только одну уникальную копию каждого строкового литерала. Это оптимизация для экономии памяти.
Как работает:
- Все строковые литералы в коде автоматически интернируются на этапе компиляции/JIT.
- При создании строки CLR сначала проверяет пул. Если строка там есть, возвращается ссылка на существующий объект.
Пример, демонстрирующий разницу:
string literal1 = "Hello";
string literal2 = "Hello"; // Тот же литерал
string dynamicStr = new StringBuilder().Append("He").Append("llo").ToString(); // Создана динамически
// Сравнение ссылок (ReferenceEquals)
Console.WriteLine(object.ReferenceEquals(literal1, literal2)); // True: оба ссылаются на один объект в пуле
Console.WriteLine(object.ReferenceEquals(literal1, dynamicStr)); // False: dynamicStr — новый объект в куче
// Принудительное интернирование динамической строки
string internedDynamic = string.Intern(dynamicStr);
Console.WriteLine(object.ReferenceEquals(literal1, internedDynamic)); // True: теперь ссылка на объект из пула
// Проверка на интернированность
Console.WriteLine(string.IsInterned("Hello") != null); // True
Console.WriteLine(string.IsInterned(dynamicStr) != null); // False (до вызова string.Intern)
Практические соображения:
- Плюс: Экономит память при множественном использовании одинаковых литералов.
- Минус: Пул живет до выгрузки домена приложения. Динамическое интернирование большого числа уникальных строк может увеличить потребление памяти без возможности сборки мусора.
- Использовать
string.Internвручную стоит только для часто повторяющихся строк, создаваемых динамически (например, ключей словаря).