Страницы

Поиск по вопросам

четверг, 18 октября 2018 г.

Как работает интернирование строк

коллеги!
хотела бы спросить вопросы, которые у меня возникли при более подробном изучении языка .NET и трудности касаются как минимум ссылочного типа string
1) Intern pool; (пулСтрок) Позволяет объединить строки с одинаковыми значениями в них в определенный пул памяти. В данном случае мы инициализировали две строки с одинаковыми значениями и они попали в один пул памяти. пример в моем понимании:
string a = "aaa"; string b = "aaa"; bool c = (object)a == (object) b; // И получаем true
ОДНАКО код:
string a = "aaa"; string b = "aa"; b+="a"; bool c = (object)a == (object) b; // И получаем false
Почему так? и как это работает? по сути мы получаем строку с одинаковыми значениями и все они должны ссылаться на один объект. почему мы по итогу получаем разные результаты? Я понимаю, что в данном случае мы сравниваем объекты, а не содержимое. Но почему они не объединились?


Ответ

В первом вашем примере строки интернируются на этапе компиляции. Если посмотреть в утилите ILDASM, то в окне MetaInfo в разделе User Strings будет представлен всего один экземпляр:
70000001 : ( 3) L"aaa"
Соответственно, обе переменные: и a, и b будут указывать на этот адрес.
Во втором примере в результате конкатенации тоже получается строка "aaa", но она не заносится по умолчанию в пул интернированных строк, потому что для этого нужны дополнительные проверки, то есть тратится время.
Во втором примере можно добавить строку в пул вручную:
string a = "aaa"; string b = "aa"; b += "a"; b = string.Intern(b); bool c = (object)a == (object)b; // True
Ответ на вопрос из комментария:
Я не уверен, но, думаю, выгода в том, что после интернирования переменная b станет указывать на тот же участок памяти, что и a. После чего сборщик мусора сможет убрать другой экземпляр строки "aaa". Это почти бессмысленно для коротких строк, но может оказаться выгодно для длинных долгоживущих строк.
Также нужно учитывать, что удалить строку из пула невозможно. Она так и будет висеть в памяти до конца работы приложения. Именно поэтому в рантайме строки не добавляются в пул по умолчанию.

Комментариев нет:

Отправить комментарий