Правило, что при присваивании переменных обычного типа другим перемеым, значения копируются, не распространяется на ситуацию, когда обычный тип
содержит в качестве члена данных ссылочный тип. Возьмем, к примеру, следуее объявление:
struct MyValueTypeWithReferenceType { public int value;
public MyReferenceType reference;
}
В ЭТОМ коде объявляется обычный тип MyValueTypeWithReferenceType, который содержит один член данных обычного типа (int ) и один член данных ссылочного типа (MyReferenceType). Это объявление нёявно указывает, что обычный тип сраняется в стеке, а ссылочный тип — в куче.
Обычным типом, содержащим ссылочный тип, можно манипулировать с помощью следующего кода:
MyValueTypeWithReferenceType var = new MyValueTypeWithReferenceType(); var.reference = new MyReferenceType();
MyValueTypeWithReferenceType copiedVar = var;
Console.WriteLine("var value=" + var.reference.value +
" copiedVar value=" + copiedVar.reference.value); var.reference.value = 10;
Console.WriteLine("var value=" + var.reference.value +
" copiedVar value=" + copiedVar.reference.value;
Важно понимать, что назначение MyValueTypeWithReferenceType не означает нначение внедренного пользовательского типа. В тестовом коде переменная типа MyValueTypeWithReferenceType назначается таким же образом, как и в предыдих примерах, но переменную типа MyReferenceType требуется назначать снова, Т. К. ти п MyReferenceType являетс я ССЫЛОЧНЫМ. Есл и бы ти п MyReferenceType был обычным, то второе назначение не было бы необходимым. Но если выделить обычный тип подобно ссылочному типу, то компилятор проигнорирует эту дективу.
Результаты выполнения предыдущего кода будут следующими:
var value=0 copiedVar value=0 var value=10 copiedVar value=10
Когда выделяется и модифицируется внедренный ссылочный тип, то экземпляр ссылочного типа модифицируется для обеих переменных. В данном случае при присваивании обычного типа было скопировано содержимое, включая указатель на ссылочный тип.
Поведение типов при присваивании выделенной переменной другой переменной с последующей модификацией элемента данных в первоначальной переменной изложено в табл. 4.1. Например, если выполнить код custom2 = customi; customi .member = [новое значение], каким будет значение члена custom2 .member?
Таблица 4.1. Поведение типов при присваивании выделенной переменной другой переменной с последующей модификацией элемента данных в первоначальной переменной
Ти п |
Поведение |
Обычный тип |
Присвоенный элемент данных не модифицируется |
Ссылочный тип |
Присвоенный элемент данных модифицируется |
Обычный тип с внедренным обыым типом |
Присвоенный внедренный элемент данных не мифицируется |
Обычный тип с внедренным ссочным типом |
Присвоенный внедренный элемент данных модифируется |
Ссылочный тип с внедренным обычным типом |
Присвоенный внедренный элемент данных модифируется |
Ссылочный тип с внедренным ссочным типом |
Присвоенный внедренный элемент данных модифируется |
Источник: Гросс К. С# 2008: Пер. с англ. — СПб.: БХВ-Петербург, 2009. — 576 е.: ил. — (Самоучитель)