Две разные "строки" - это один и тот же экземпляр объекта?

Код довольно понятен. Я ожидал, когда я сделал a1 и b1, что я создавал два разных экземпляра строк, которые содержат один и тот же текст. Поэтому я считаю, что a1 == b1 будет true, но object.ReferenceEquals(a1,b1) будет ложным, но это не так. Почему?

//make two seemingly different string instances
string a1 = "test";
string b1 = "test";         
Console.WriteLine(object.ReferenceEquals(a1, b1)); // prints True. why?

//explicitly "recreating" b2
string a2 = "test";
string b2 = "tes";
b2 += "t";    
Console.WriteLine(object.ReferenceEquals(a2, b2)); // prints False

//explicitly using new string constructor
string a3 = new string("test".ToCharArray());
string b3 = new string("test".ToCharArray());    
Console.WriteLine(object.ReferenceEquals(a3, b3)); // prints False

Ответ 1

Литеральные строковые объекты объединяются в отдельные экземпляры компилятором. Фактически это требуемое спецификацией:

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

Ответ 2

Компилятор оптимизирован так, что строковые литералы if равны с оператором "==", чем нет необходимости создавать новый экземпляр, и оба относятся к одному экземпляру... Итак, почему ваша первая часть вопроса ответил True.

Хотя строка является ссылочным типом, операторы равенства (== и! =) определены для сравнения значений строковых объектов, а не ссылок. Это делает тестирование для равенства строк более интуитивным. Например:

string a = "hello";
string b = "h";
// Append to contents of 'b'
b += "ello";
Console.WriteLine(a == b);
Console.WriteLine((object)a == (object)b);

Отображается "True", а затем "False", потому что содержимое строк эквивалентно, но a и b не относятся к одному и тому же экземпляру строки.

Оператор + связывает строки:

string a = "good " + "morning";

Это создает строковый объект, содержащий "доброе утро".

Строки неизменяемы - содержимое строкового объекта не может быть изменено после создания объекта, хотя синтаксис делает его таким, как будто вы можете это сделать. Например, когда вы пишете этот код, компилятор фактически создает новый строковый объект для хранения новой последовательности символов, а новый объект присваивается b. Затем строка "h" имеет право на сбор мусора.

string b = "h";
b += "ello";

для дополнительной справки проверьте это на msdn и на этом

Ответ 3

Компилятор оптимизирует этот случай и дает им одну и ту же ссылку на строку. Является ли строка в С# неизменной?

Ответ 4

Оптимизация компилятора. Просто как это.