2015-02-02 3 views
0

У меня есть простой концептуальный вопрос в C#. В строках C# указаны ссылочные типы. Поэтому это означает, что когда я создаю строковую переменную «ABC», она будет содержать ссылку или адрес фактического массива символов в управляемой куче.String Manipulation в .NET C#

Итак, если я пишу:

string ABC = "Hye"; 
String XYZ = ABC; 
ABC = ABC.Replace("H","B"); 

Console.WriteLine("ABC - "+ ABC); 
Console.WriteLine("XYZ - "+ XYZ); 

Actual Выход:

ABC - Bye 
XYZ - Hye 

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

Может ли кто-нибудь сказать мне, где я ошибаюсь?

+0

Ответ на этот вопрос «потому что строка неизменна в .NET». Это подсказывает следующий вопрос: почему они неизменны? - на который отвечает ссылка выше. – Yuck

+2

@aloisdg: Достаточно разумно ожидать, что изменение в строке будет видно из обеих переменных, так как это именно то, что произойдет. То, что отсутствует в рассуждениях, состоит в том, что строки неизменяемы, поэтому изменений в строке не будет. – Guffa

ответ

5

Давайте посмотрим на ваш код по строкам;

string ABC = "Hye"; 

С этой линией, вы создали объект строки, как "Hye" и ссылка на этот объект называется ABC.

enter image description here

String XYZ = ABC; 

С этой линией, вы создали ссылку под названием XYZ и эта ссылка со ссылкой на тот же объект с ABC ссылкой, которая "Hye"

enter image description here

ABC = ABC.Replace("H","B"); 

Поскольку строки immutable types, String.Replace() method не изменяет исходный объект. Он возвращает новый объект и вашу ссылку ABC со ссылкой на этот объект, который является "Bye". Он не ссылается на старый объект больше.

enter image description here

+2

О боже, мне жаль, что у меня не было больше навыков в MS Paint. –

3

Я думаю, что эта линия:

ABC = ABC.Replace("H","B"); 

создает новый экземпляр String. От MSDN: Этот метод не изменяет значение текущего экземпляра. Вместо этого он возвращает новую строку, в которой все вхождения oldValue заменяются newValue. не

Info - MSDN

2

Короткая версия: Нет это не должно указывать на тот же адрес. Он указывал на тот же адрес, но вы заменили адрес в ABC другим (результат замены).

Длинная версия

Подумайте об этом так - оператор присваивания (=), а также передать аргументы метода и возвращающие значения из метода всегда делает копию. Разница между ссылочными типами и типами значений - это то, что копируется. Когда значение представляет собой тип значения, все данные в памяти копируются в другое место в памяти. Сама переменная содержит данные. При работе со ссылочными типами переменная (как аргумент метода и возвращаемое значение метода) содержит адрес объекта в памяти. Вот почему, когда вы назначаете одну переменную другой, они указывают на один и тот же объект. Обе переменные сохраняют один и тот же адрес. Однако оператор = все еще выполняет копию одной переменной в другую. Он копирует адрес. Поэтому, когда вы назначаете возвращаемое значение из метода replace, вы копируете адрес новой строки в переменной ABC. Вы не копируете ничего в другой переменной. Они указывали на один и тот же объект, но теперь это не так, потому что адрес, скопированный в ABC, теперь отличается. Переменные ссылочных типов не связаны некоторой магией, с которой они связаны тем фактом, что они содержат адреса одного и того же объекта, но сами адреса являются просто цифрами. Если вы используете оператор = для переменной, вы заменяете объект. Если вы измените объект, значение изменится в обеих переменных, но если вы замените объект, переменные будут содержать разные объекты.

Обратите внимание, что это справедливо и для аргументов метода.

List<string> list = new List<String> { "asdf" }; 
SomeMethod(list); 
//list contains "asdf", "fdsa" 
SoemOtherMethod(list), 
//list is NOT null 

static void SomeMethod(List<string> list) 
{ 
    list.Add("fdsa"); //changes the original list 
} 

static void SomeOtherMethod(List<string> list) 
{ 
    list = null; //cannot replace the original list only replaces the address in the argument variable 
} 
+0

Хорошо, насколько я понимаю из вашего комментария. [ABC = ABC.Replace ("H", "B")] создает другой массив символов в куче, и теперь ABC указывает на него вместо исходной ссылки. Я прав? –

+0

Да, да. строки в .NET не могут меняться (обычно без серьезного взлома). Все методы, которые изменяют строки, такие как replace, создают новый строковый объект с внесенными изменениями. – Stilgar