Поскольку строки неизменяемы, указывают ли переменные с одинаковыми строковыми значениями на один и тот же строковый объект? - PullRequest
16 голосов
/ 09 февраля 2010

а)

        string s  = "value";
        string s1 = "value";

Указывают ли ссылочные переменные s и s1 на один и тот же строковый объект (я предполагаю, что это из-за того, что строки неизменяемы)?

b) Я понимаю, что операторы равенства (==,> и т. Д.) Были переопределены для сравнения значений строковых объектов, но то же самое верно при сравнении двух строк с использованием статических методов Object.Equals () и Object.ReferenceEquals ()

1008 * спасибо *

Ответы [ 3 ]

21 голосов
/ 09 февраля 2010

Нет, не все строки с одинаковыми значениями имеют одинаковую ссылку на объект.

Все строки, сгенерированные компилятором, будут Interned и будут одной и той же ссылкой. Строки, генерируемые во время выполнения, по умолчанию не интернированы и будут разными ссылками.

var s1 = "abc";
var s2 = "abc";
var s3 = String.Join("", new[] {"a", "b", "c"});
var s4 = string.Intern(s3); 
Console.WriteLine(ReferenceEquals(s1, s2)); // Returns True
Console.WriteLine(ReferenceEquals(s1, s3)); // Returns False
Console.WriteLine(s1 == s3); // Returns True
Console.WriteLine(ReferenceEquals(s1, s4)); // Returns True

Обратите внимание на строку выше, где вы можете принудительно интернировать строку, используя String.Intern(string), которая затем позволяет вам использовать равенство объектов вместо равенства строк для некоторых проверок, что намного быстрее. Один пример, где это очень часто используется, находится внутри сгенерированного кода XML-сериализатора вместе с таблицей имен.

3 голосов
/ 09 февраля 2010

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

Это потому, что .NET Framework вставляет строковые литералы в вашей программе в пул интернирования. Вы можете использовать String.Intern , чтобы получить эту ссылку или вручную интернировать вашу собственную, сгенерированную во время выполнения строку.

Для получения более подробной информации см. документы для стажера :

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

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

2 голосов
/ 09 февраля 2010

С текущей CLR идентичные литеральные строки указывают на одинаковые фактические объекты. Процесс называется интернированием и применяется ко всем строкам времени компиляции.

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

Пожалуйста, смотрите мой ответ на этот вопрос для подробного объяснения того, как хранятся строки .NET.

...