Строковые литералы оптимизируются компилятором? - PullRequest
15 голосов
/ 26 ноября 2010

Компилятор C # или .NET CLR выполняет какую-либо умную оптимизацию памяти строковых литералов / констант?Я мог бы поклясться, что слышал о понятии «интернализация строк», так что в любых двух битах кода в программе литерал «это строка» фактически ссылается на один и тот же объект (предположительно безопасный, что со строкаминеизменный?).Я не могу найти какую-либо полезную ссылку на это в Google, хотя ...

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

Ответы [ 4 ]

17 голосов
/ 26 ноября 2010

EDIT: хотя я сильно подозреваю, что приведенное ниже утверждение верно для всех реализаций компилятора C #, я не уверен, что оно действительно гарантировано в спецификации. В разделе 2.4.4.5 спецификации говорится о литералах , ссылающихся на тот же экземпляр строки, но в нем не упоминаются другие константные строковые выражения. Я подозреваю это упущение в спецификации - я напишу об этом Мэдсу и Эрику.


Это не просто строковые литералы. Это любая строка константа . Так, например, рассмотрим:

public const string X = "X";
public const string Y = "Y";
public const string XY = "XY";

void Foo()
{
    string z = X + Y;
}

Компилятор понимает, что конкатенация здесь (для z) находится между двумя константными строками, и поэтому результат также является константной строкой. Поэтому начальное значение z будет той же ссылкой, что и значение XY, поскольку они являются константами времени компиляции с тем же значением.

РЕДАКТИРОВАТЬ: Ответ Мэдс и Эрик предположил, что в строковых константах компилятора Microsoft C # и строковых литералах обычно обычно обрабатываются одинаково - но другие реализации могут отличаться.

7 голосов
/ 26 ноября 2010

Да, это оптимизирует строковые литералы.Один простой пример, где вы можете увидеть это:

string s1="A";
string s2="A";
object.ReferenceEquals(s1,s2);  //true
7 голосов
/ 26 ноября 2010

Эта статья довольно хорошо объясняет интернирование строк. Цитата:

.NET имеет понятие "стажер бассейн ". Это в основном просто набор строки, но это гарантирует, что каждый раз вы ссылаетесь на одну и ту же строку буквально, вы получаете ссылку на та же строка Это наверное зависит от языка, но это, безусловно, правда в C # и VB.NET, и я бы очень удивлен, увидев язык это не держись, так как IL делает это очень легко сделать (вероятно, легче, чем не интерны литералы). Как и литералы будучи автоматически интернированным, вы можете внутренние строки вручную с Стажер, и проверьте, или нет уже интернированного строка с тем же символом Последовательность в пуле, используя Метод IsInterned. Это несколько неинтуитивно возвращает строку скорее чем логическое - если равная строка в бассейне, ссылка на это строка возвращается. В противном случае ноль вернулся. Точно так же, метод Intern возвращает ссылку на интернированного строка - либо строка, которую вы передали если был уже в бассейне, или вновь созданная интернированная строка или равная строка, которая уже была в бассейн.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...