почему ReferenceEquals (s1, s2) возвращает true - PullRequest
15 голосов
/ 20 ноября 2010
  String s1 = "Hello";
  String s2 = "Hello";

Здесь s1, s2 разные, но почему ReferenceEquals () возвращает true

Ответы [ 5 ]

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

Это происходит из-за интернирования - CLI автоматически повторно использует строки, полученные в качестве литералов (т.е. строки, которые были получены непосредственно из вашего исходного кода).Обратите внимание, что если бы вы сделали:

char[] chars = {'h','e','l','l','o'};
string s1 = new string(chars);
string s2 = new string(chars);

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

Это задокументировано для Ldstr Инструкция IL :

Инфраструктура общего языка (CLI) гарантирует, что результат двух инструкций ldstr, относящихся к двум токенам метаданных, которые имеют одинаковую последовательность символов, возвращает точнотот же строковый объект (процесс, известный как «интернирование строк»).

2 голосов
/ 20 ноября 2010

String is immutable, поэтому используется та же ссылка для того же значения. См. Также Eric lippert блог обо всем этом

2 голосов
/ 20 ноября 2010

Строки являются неизменяемыми, после того как они созданы в памяти, следующие те же объекты String ссылаются на ранее созданный объект String. для большего http://msdn.microsoft.com/en-us/library/362314fe.aspx

1 голос
/ 20 ноября 2010

Вы также можете использовать String.Copy(String str) статический метод для создания строк, которые будут разными объектами

String s1 = "Hello";
String s2 = string.Copy("Hello");

тогда s1 и s2 будут ссылаться на разные объекты.

1 голос
/ 20 ноября 2010

если вы гуглите "ReferenceEquals string"

вы получите это

Ниже был принят ответ по ссылке, на случай, если ссылка умрет

В этом примере "obj1" и "obj2" - это отдельные экземпляры, верно?

Нет - строки являются ссылочными типами, а obj1 и obj2 - две переменные, указывающие на один и тот же экземпляр, частично из-за того, что называется интернированием; в принципе, любой строковый литерал в сборке * может иметь одну и ту же строковую ссылку. Это возможно только потому, что строки неизменны. Вы также можете проверить интернированные строки (string.IsInterned) и вручную интернировать, если хотите (string.Intern).

Когда две строки имеют одинаковое значение, они разделяют один и тот же экземпляр?

Они могут иметь один и тот же экземпляр; но это не гарантировано. Строки, которые генерируются на лету, обычно не интернируются; например, единственные, которые делятся ссылками здесь, это 2 & 4:

string tmp1 = "aa", tmp2 = "aaa";

строка s1 = новая строка ('a', 5),

s2 = "ааааа",

s3 = tmp1 + tmp2,

s4 = "ааааа";

Console.WriteLine (ReferenceEquals (s1, s2));

Console.WriteLine (ReferenceEquals (s1, s3));

Console.WriteLine (ReferenceEquals (s1, s4));

Console.WriteLine (ReferenceEquals (s2, s3));

Console.WriteLine (ReferenceEquals (s2, s4));

Console.WriteLine (ReferenceEquals (s3, s4));

* = строго: net-module

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