Страницы

Поиск по вопросам

четверг, 5 декабря 2019 г.

Вопрос про ссылочные типы данных

#c_sharp


Если 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);
}



    


Ответы

Ответ 1



У переменной значимого типа значение хранится в самой переменной. У переменной ссылочного типа в переменной хранится ссылка на некоторую область памяти, в которой в свою очередь хранится значение. Теперь о типе 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; все три переменный будут ссылаться на одну область памяти, но любое изменение, любой из них не затронет остальные две, а просто породит еще одну строку. Подробней можно почитать, например: Строки, неизменяемость и персистентность. Типы значений и ссылочные типы

Ответ 2



Смотрите, String действительно является ссылочным типом, но ведет он себя в CLR несколько специфично, чтобы походить на тип значения. Поскольку строка традиционно относится к "базовым" типам, таким как int, double, Array, то программист подсознательно ожидает от строки поведения не как ссылочного, а как значимого типа. Для обеспечения такого поведения, при присваивании переменной строкового типа нового литерала каждый раз создается новый объект, а переменной возвращается ссылка на этот новый объект. Таким образом, строку var someString = "Value"; Можно воспринимать как такой псевдокод var someString = new String(Char[]{'V','a','l','u','e'}); UPDATE Если объект типа string со значением "Value" уже существует, то CLR попытается не создавать новый объект, а вернет ссылку на уже существующий. Как вывод, string это ссылочный тип, который передает свое значение ни как объект, а как ссылка на объект.

Ответ 3



здарвствуйте я вам попробую обьяснить более понятным языком. Предположим вы создали 4 переменных типа стринг а потом сделали следующее string s1 = "qwer"; string s2 = "abcd"; string s3 = s1; string s4 = s2; теперь у вас в s1 указывает на ту часть памяти где записана строка s3 также заметьте что s3 не указывает на ссылку s1 а именно на место памяти тоесть если мы изменим значение s1 или s3 другое значение не изменится. Также и с s2,s4. Думаю что разумно и доступно обьяснил желаю удачи. Теперь раз уж вы все это знаете попробуйте подумать и сказать без написания кода и компиляции что будет если сделать так s4 = s1; s1 = "1456"; какое будет значение у s1,s2,s3,s4?

Комментариев нет:

Отправить комментарий