Если string
является ссылочным типом, как и class
, то почему у str1
и str2
разные значения? По идее обе переменных должны ссылаться на одну и ту же область памяти в куче, как country1
и country2
static void Main(string[] args)
{
Country country1 = new Country();
country1.x = 1;
country1.y = 2;
Console.WriteLine("Country1 {0}, {1}", country1.x, country1.y);
Country country2 = new Country();
country2 = country1;
country1.x = 3;
Console.WriteLine("Country1 {0}, {1}", country1.x, country1.y);
Console.WriteLine("Country2 {0}, {1}", country2.x, country2.y);
///////////////////
string str1;
str1 = "123";
Console.WriteLine("Str1 {0}", str1);
string str2;
str2 = str1;
str1 = "1234";
Console.WriteLine("Str1 {0}", str1);
Console.WriteLine("Str2 {0}", str2);
}
У переменной значимого типа значение хранится в самой переменной. У переменной ссылочного типа в переменной хранится ссылка на некоторую область памяти, в которой в свою очередь хранится значение. Теперь о типе string
, переменная такого типа хранит ссылку, но нюанс состоит в том, что выделенная память, на которую это ссылка указывает является неизменяемой, поэтому каждый раз когда вы проводите какие либо манипуляции со строкой вы, фактически создаете новый объект в памяти. И такие манипуляции затронут, только, непосредственно, ту переменную которая подверглась изменениям. Давайте рассмотрим ваш пример.
string str1; //здесь вы создали переменную str1, но она еще ни на что не ссылается
str1 = "123"; //здесь в переменную str1 записывается адрес литерала "123"
string str2;
str2 = str1; //здесь мы записали в переменную str2, значение адреса литерала "123"
//который сохранен в переменной str1
str1 = "1234"; //а вот сейчас мы пишем в str1 ссылку на совершенно другой литерал
//а в str2 остается старое значение, так с этой переменной
//вы никаких манипуляций не проводили
Да, небольшое добавление. Если вы сделаете так:
string str1 = "1234";
string str2 = str1;
string str3 = str1;
все три переменный будут ссылаться на одну область памяти, но любое изменение, любой из них не затронет остальные две, а просто породит еще одну строку.
Подробней можно почитать, например:
Смотрите, String действительно является ссылочным типом, но ведет он себя в CLR несколько специфично, чтобы походить на тип значения. Поскольку строка традиционно относится к "базовым" типам, таким как int, double, Array, то программист подсознательно ожидает от строки поведения не как ссылочного, а как значимого типа. Для обеспечения такого поведения, при присваивании значения переменной строкового типа каждый раз создается новый объект, а переменной возвращается ссылка на этот новый объект.
Таким образом, строку
var someString = "Value";
Можно воспринимать как такой псевдокод
var someString = new String(Char[]{'V','a','l','u','e'});
Кофе для программистов: как напиток влияет на продуктивность кодеров?
Рекламные вывески: как привлечь внимание и увеличить продажи
Не запускается простейшее ARKit приложениеПросто исходная демо сцена из ARKit для Unity