Недопонимание внутренних строковых литералов? - PullRequest
5 голосов
/ 01 января 2012

Я не понимаю:

MSDN говорит

http://msdn.microsoft.com/en-us/library/system.string.intern.aspx

Следовательно, экземпляр литеральной строки с определенным значением существует только один раз в системе.

Например, если вы назначаете одну и ту же буквенную строку нескольким переменных, среда выполнения получает ту же ссылку на литерал строка из пула стажеров и присваивает ее каждой переменной.

Это поведение по умолчанию (без стажера)? или с помощью метода интерна?

  • Если по умолчанию, так почему я хочу использовать интерна? (экземпляр уже будет один раз ...)?

  • Если это НЕ по умолчанию: если я напишу 1000 раз эту строку:

    Console.WriteLine ( "Лалала");

1) я получу 1000 экземпляров "lalala" в памяти? (без использования интерна ...)

2) будет ли "лалала" со временем Gc'ed?

3) "Лалала" уже интернирована? и если да, то почему мне нужно «получить» его из пула, а не просто снова написать «lalala»?

Я немного запутался.

Ответы [ 2 ]

9 голосов
/ 01 января 2012

Строковые литералы извлекаются автоматически (поэтому, если ваш код содержит «lalala» 1000 раз, будет существовать только один экземпляр).

Такие строки не будут получать GC'd и каждый раз, когда они ссылаются на ссылкубудет интернированным.


string.Intern есть для строк, которые являются не литералами - скажем, из пользовательского ввода или чтения из файла или базы данных, и вы знаю, что будет повторяться очень часто и, как таковые, стоит проходить практику на протяжении всего жизненного цикла процесса.

5 голосов
/ 01 января 2012

Стажировка - это то, что происходит за кулисами, поэтому вам, как программисту, никогда не придется беспокоиться об этом.Как правило, вам не нужно ничего класть в бассейн или получать что-либо из пула.Как сборка мусора: вам никогда не придется вызывать его, или беспокоиться о том, что это может произойти, или беспокоиться о том, что это может не произойти.(Ну, в 99,999% случаев. А оставшиеся 0,001 процента - это когда вы делаете очень странные вещи.)

Компилятор заботится о интернировании всех строковых литералов, содержащихся в вашем исходном файле, поэтому "Лалала "будет интернирована без необходимости что-либо делать или контролировать ситуацию.И всякий раз, когда вы ссылаетесь на «lalala» в своей программе, компилятор обязательно выбирает ее из внутреннего пула, опять же, без необходимости что-либо делать и не иметь никакого контроля над этим вопросом.

Внутренний пул содержитболее или менее фиксированное количество строк, как правило, очень маленького размера (только часть общего размера вашего .exe), поэтому не имеет значения, что они никогда не будут собирать мусор.


EDIT

Цель интернирования строк - значительно улучшить время выполнения некоторых строковых операций, таких как Equals ().Метод Equals() String сначала проверяет, равны ли строки по ссылке, что очень быстро;если ссылки равны, то немедленно возвращается true;если ссылки не равны, и обе строки интернированы, то он немедленно возвращает false, поскольку они не могут быть равны, поскольку все строки в пуле интернирования отличаются друг от друга.Если ничего из вышеперечисленного не выполняется, тогда выполняется последовательное сравнение строк за символом.(На самом деле, это даже сложнее, потому что он также проверяет хеш-коды строк, но в этом обсуждении все будет просто.)

Итак, предположим, что вы читаете токены из файла в строкеs, и у вас есть оператор switch следующего вида:

switch( s )
{
    case "cat": ....
    case "dog": ....
    case "tod": ....
}

Строковые литералы "cat", "dog", "tod" все интернированы, но вы сравниваете каждый из ниходин из них против s, который не был интернирован, так что вы не пожинаете плоды стажировки.Если вы интернируете s прямо перед оператором switch, то сравнения, которые будут выполняться оператором switch, будут выполняться намного быстрее.

Конечно, если есть вероятность, что ваш файл может содержать мусор,тогда вы НЕ хотите этого делать, потому что загрузка большого количества случайных строк в пул интернационала наверняка снизит производительность вашей программы и в конечном итоге исчерпает память.

...