#c#
#c#
Вопрос:
Я знаю, что string является ссылочным типом, но у меня возникают проблемы с пониманием того, почему string вне класса или функции «refTest» не будет вести себя так, как внутри класса «refTest». Я имею в виду, если у меня есть 2 строки с именами «name» и «name2», и обе имеют одинаковое значение, поскольку name2 имеет копию name, оно будет выводить одно и то же значение «A», но затем я меняю второе строковое значение на «B», и на этот раз name и name2 имеют разные значениязначение «A» и «B», а затем, когда я проделаю то же самое со строкой из класса «refTest», она выведет name1 и name2 с одинаковым значением. Разве оба типа string не являются ссылочными? Это означает, что у них есть указатель на кучу. Верно? Я запутался в том, почему строка вне класса «refTest» выдаст другой результат по сравнению с тем, который находится внутри класса «refTest».
Или дело в том, что каждый раз, когда я объявляю строку вне класса «refTest», она будет храниться на другом адресе (адрес кучи)?
class Program
{
static void Main(string[] args)
{
string name = "A";
string name2 = name;
Console.WriteLine(name2 " " name);
// >> A A
name2 = "B";
Console.WriteLine(name2 " " name);
// >> A B
refTest test = new refTest();
test.rTName = "A";
Console.WriteLine(test.rName);
// >> A
refTest test2 = test;
test2.rName = "B";
Console.WriteLine($"test.rName = {test.rName}, test2.rName = {test2.rName}");
// >> test.rName = B, test2.rName = B
Console.ReadLine();
}
}
class refTest
{
public string rName;
}
Комментарии:
1.
test
иtest2
это одно и то же; чего вы ожидаете, чтобы быть другим? (ps; Я так понимаю, этоtest.rTName
опечатка?)2. Строки в C # сильно отличаются от строк в Java или массивов символов в C. Ответ Магнетрона объясняет, как работают строки в C #.
Ответ №1:
string
, хотя и является ссылочным типом, он является неизменяемым. Это означает, что когда вы это делаете name2 = "B"
, вы создаете новый экземпляр и name2
указываете на новый экземпляр, в то name
же время указывая на старый.
Теперь для вашего пользовательского класса, когда refTest test2 = test;
вы это делаете test2
, вы указываете на тот же объект, test
что и , и когда вы изменяете свойство или поле в одном из них, поскольку они оба указывают на один и тот же объект, оба test
и test2
будут отображать новое значение.
Комментарии:
1. Теперь все ясно. Спасибо. Итак, каждый раз, когда я объявляю строку в основной функции, это означает, что я «создаю» новый адрес (кучу)? И я знаю эту кучу .
2. это не объявление, которое создает новый экземпляр, это присвоение @twinspectre ..
System.String
является ссылочным типом. он будетnull
иметь размер 0 байт до тех пор, пока ему не будет присвоен (или создан экземпляр).3. итак, если у меня есть строка с именем Characters (я знаю, что для отдельных символов есть символ char), и я присваиваю = «A», и я использую ту же переменную, и я присваиваю «B», означает ли это, что A будет «сохранен» по своему исходному адресу, а B (та же переменная, что и раньше) будут ли они «сохранены» на другом адресе?
4. Я не знаю, сохранятся ли эти ссылки, но вот скриншот кучи неустановленной строки pasteboard.co/JJl2RhX.png обратите внимание, что args — это массив строк. и через пару шагов он создается. pasteboard.co/JJl6h64.png
5. Я скажу, что, хотя я ожидал увидеть
string name2 = name
be created в куче как новый экземпляр (хотя в моем ss это былоtestString2 = testString1
), этого не было .. по крайней мере, не в области Main . Хотя, возможно, в области Encoder, поскольку сравнение этих снимков действительно представляло увеличение размера.
Ответ №2:
Вот что происходит в памяти по мере выполнения вашего кода (только назначения). На самом деле речь идет не о неизменности строки, а о том, что указывает на что:
Никогда не бывает так, чтобы приравнивание одной переменной к другой устанавливало цепочку
string x = "hello";
string y = x;
Оба y
и x
указывают на «привет». Это не тот случай, когда «y указывает на x, а затем x указывает на hello, и если вы измените, на что указывает x, y это увидит»
YES: y --> hello <-- x
NO: y --> x --> hello
Но у вас есть цепочка, когда какая-то переменная указывает на класс, и у этого класса есть переменная, которая указывает на что-то еще. Это то, что у вас было с вашим refTest ; ваш test
и test2
указывает на экземпляр reftest , который указывает на имя A , а позже вы заменили имя.. Это устанавливает цепочку ссылок, в которой замена некоторой части цепочки означает, что что-то вышестоящее видит это
Комментарии:
1. Каждый раз, когда я объявляю переменную, это означает, что в куче «создается» новый адрес.
2. Я собираюсь сказать «нет», но не совсем понятно, что вы имеете в виду. Читайте о том, как стек и куча используются в C #. Избегайте попадания в ловушки чрезмерно упрощенных эмпирических правил, таких как «типы значений находятся в стеке, а ссылочные типы — в куче». Ваш вопрос на самом деле не имеет никакого отношения к стеку и куче