Стажирующие строки почти не дадут пользы в большинстве сценариев использования строк, даже если у них будет пул интернинга со слабой ссылкой нулевой стоимости (идеальная реализация интернирования). Чтобы интернирование строк могло принести какую-либо пользу, необходимо, чтобы несколько ссылок на совпадающие строки совпадали в течение достаточно «длительного» времени.
Рассмотрим следующие две программы:
- Введите 100 000 строк из текстового файла, каждая из которых содержит произвольный текст, а затем 100 000 пятизначных чисел. Рассматривайте каждое число, считываемое в виде индекса с нуля, в список из 100 000 строк, которые были прочитаны, и выводите соответствующую строку на выход.
- Введите 100 000 строк из текстового файла, выводя каждую строку, содержащую последовательность символов «fnord».
Для первой программы, в зависимости от содержимого текстового файла, интернирование строк может привести к почти 50 000: 1 экономии памяти (если строка содержит 100 000 идентичных длинных строк текста) или может представлять собой общую потерю (если все 100 000 строк разные). При отсутствии интернирования строк входной файл с 100 000 одинаковых строк приведет к тому, что 100 000 действующих экземпляров одной и той же строки будут существовать одновременно . Благодаря интернированию строк количество живых экземпляров может быть уменьшено до двух. Конечно, компилятор не может даже попытаться угадать, может ли входной файл содержать 100 000 одинаковых строк, 100 000 различных строк или что-то промежуточное.
Для второй программы маловероятно, что даже идеальная реализация интернирования строк принесет много пользы. Даже если все 100 000 строк входного файла оказались идентичными, интернирование не могло сэкономить много памяти. Эффект интернирования заключается не в том, чтобы предотвратить создание избыточных экземпляров строк, а в том, чтобы позволить идентифицировать и отбрасывать избыточные экземпляры строк. Так как каждая строка может быть отброшена после того, как она будет проверена и либо выведена, либо нет, единственная вещь, которую интернирование может купить, - это (теоретическая) способность отбрасывать избыточные экземпляры строк (очень) немного раньше, чем было бы возможно в противном случае.
В некоторых случаях может быть полезно кэширование определенных «промежуточных» строковых результатов, но эту задачу действительно лучше оставить программисту. Например, у меня есть программа, которая должна преобразовывать много байтов в двузначные шестнадцатеричные строки. Чтобы облегчить это, у меня есть массив из 255 строк, которые содержат строковые эквиваленты значений от 00 до FF. Я знаю, что в среднем каждая строка в этом массиве будет использоваться, как минимум, сотни или тысячи раз, поэтому кэширование этих строк - огромный выигрыш. С другой стороны, строки могут быть кэшированы только потому, что я знаю, что они представляют. Я могу знать, что для любого n
0-255 String.Format("{0:X2}",n)
всегда будет давать одно и то же значение, но я бы не ожидал, что компилятор это знает.