Шрифт:
Рис. 3.14. Внутренние ссылки указывают на один и тот же объект
Как видите, при изменении значения информирующей строки с помощью ссылки r2 ссылка r1 отображает точно такое же значение. По умолчанию, когда тип, характеризуемый значением, содержит ссылочные типы, присваивание приводит к копированию ссылок. В результате вы получаете две независимые структуры, каждая из которых содержит ссылки, указывающие на один и тот же объект в памяти (т.е. "поверхностную копию"). Если вы хотите иметь "детальную копию", когда состояние внутренних ссылок полностью Копируется в новый объект, необходимо реализовать интерфейс ICloneable (это будет обсуждаться в главе 7).
Исходный код. Проект ValAndRef размещен в подкаталоге, соответствующем главе 3.
Передача ссылочных типов по значению
Очевидно, что ссылочные типы могут передаваться членам типов, как параметры. Но передача объекта по ссылке отличается от его передачи по значению. Чтобы понять суть различий, предположим, что у нас есть класс Person (персона), определенный следующим образом.
Теперь создадим метод, который позволяет вызывающей стороне переслать тип Person по значению (обратите внимание на отcутcтвие модификаторов параметра).
Обратите внимание на то, что метод SendAPersonByValue пытается изменить получаемую ссылку Person на новый объект, а также изменить некоторые данные состояния. Давайте проверим работу этого метода, используя следующий метод Main.
На рис. 3.15 показан соответствующий вывод.
Рис. 3.15. Передача ссылочных типов по значению блокирует соответствующую ссылку
Как видите, значение возраста (age) изменяется. Кажется, такое поведение при передаче параметра противоречит самому термину "по значению". Если вы способны изменить состояние получаемого объекта Person, что же все-таки копируется? Ответ здесь следующий: в объект вызывающей стороны копируется ссылка. Поэтому, поскольку метод SendAPersonByValue и объект вызывающей стороны указывают на один и тот же объект, можно изменить состояние данных объекта. Что здесь невозможно, так это изменить саму ссылку так, чтобы она указывала на другой объект (это напоминает ситуацию с постоянными указателями в C++).