Читаем Язык программирования С# 2005 и платформа .NET 2.0. полностью

Как видите, при изменении значения информирующей строки с помощью ссылки r2 ссылка r1 отображает точно такое же значение. По умолчанию, когда тип, характеризуемый значением, содержит ссылочные типы, присваивание приводит к копированию ссылок. В результате вы получаете две независимые структуры, каждая из которых содержит ссылки, указывающие на один и тот же объект в памяти (т.е. "поверхностную копию"). Если вы хотите иметь "детальную копию", когда состояние внутренних ссылок полностью Копируется в новый объект, необходимо реализовать интерфейс ICloneable (это будет обсуждаться в главе 7).

Исходный код. Проект ValAndRef размещен в подкаталоге, соответствующем главе 3.

<p>Передача ссылочных типов по значению</p>

Очевидно, что ссылочные типы могут передаваться членам типов, как параметры. Но передача объекта по ссылке отличается от его передачи по значению. Чтобы понять суть различий, предположим, что у нас есть класс Person (персона), определенный следующим образом.

class Person {

 public string fullName;

 public byte age;

 public Person(string n, byte a) {

  fullName = n;

  age = a;

 }

 public Person() {}

 public void PrintInfo() { Console.WriteLine("{0}, {1} года (лет)", fullName, age); }

}

Теперь создадим метод, который позволяет вызывающей стороне переслать тип Person по значению (обратите внимание на отcутcтвие модификаторов параметра).

public static void SendAPersonByValue(Person p) {

 // Изменяет ли это возраст 'р'?

 p.age = 92;

 // Увидит ли вызывающая сторона такие изменения?

 p = new Person ("Никки", 192);

}

Обратите внимание на то, что метод SendAPersonByValue() пытается изменить получаемую ссылку Person на новый объект, а также изменить некоторые данные состояния. Давайте проверим работу этого метода, используя следующий метод Main().

static void Main(string[] args) {

 // Передача ссылочных типов по значению.

 Console.WriteLine("*** Передача объекта Person по значению ***");

 Person fred = new Persоn("Фред", 2);

 Console.WriteLine("Person до вызова по значению");

 fred.PrintInfo();

 SendAPersonByValue(fred);

 Console.WriteLine("Persоn после вызова по значению");

 fred.PrintInfо();

}

На рис. 3.15 показан соответствующий вывод.

Рис. 3.15. Передача ссылочных типов по значению блокирует соответствующую ссылку

Как видите, значение возраста (age) изменяется. Кажется, такое поведение при передаче параметра противоречит самому термину "по значению". Если вы способны изменить состояние получаемого объекта Person, что же все-таки копируется? Ответ здесь следующий: в объект вызывающей стороны копируется ссылка. Поэтому, поскольку метод SendAPersonByValue() и объект вызывающей стороны указывают на один и тот же объект, можно изменить состояние данных объекта. Что здесь невозможно, так это изменить саму ссылку так, чтобы она указывала на другой объект (это напоминает ситуацию с постоянными указателями в C++).

<p>Передача ссылочных типов по ссылке</p>

Теперь предположим, что у нас есть метод SendAPersonByReference(), который передает ссылочный тип по ссылке (обратите внимание на то, что здесь присутствует модификатор параметра ref).

public static void SendAPersonByReference(ref Person p) {

 // Изменение некоторых данных 'р'.

 p.age = 122;

 // Теперь 'р' указывает на новый объект в динамической памяти!

 р = new Person("Никки", 222);

}

Как вы можете догадаться сами, это обеспечивает вызывающей стороне полную гибкость в управлении входными параметрами. Вызывающая сторона не только может изменить состояние объекта, но и переопределить ссылку так, чтобы она указывала на новый тип Person. Рассмотрите следующий вариант.

static void Main(string[] args) {

 // Передача ссылочных типов по ссылке.

 Console.WriteLine("\n*** Передача объекта Person по ссылке ***");

 Person mel = new Person("Мэл", 23);

 Console.WriteLine("Person до вызова по ссылке:");

 mel.PrintInfo();

Перейти на страницу:

Похожие книги

97 этюдов для архитекторов программных систем
97 этюдов для архитекторов программных систем

Успешная карьера архитектора программного обеспечения требует хорошего владения как технической, так и деловой сторонами вопросов, связанных с проектированием архитектуры. В этой необычной книге ведущие архитекторы ПО со всего света обсуждают важные принципы разработки, выходящие далеко за пределы чисто технических вопросов.?Архитектор ПО выполняет роль посредника между командой разработчиков и бизнес-руководством компании, поэтому чтобы добиться успеха в этой профессии, необходимо не только овладеть различными технологиями, но и обеспечить работу над проектом в соответствии с бизнес-целями. В книге более 50 архитекторов рассказывают о том, что считают самым важным в своей работе, дают советы, как организовать общение с другими участниками проекта, как снизить сложность архитектуры, как оказывать поддержку разработчикам. Они щедро делятся множеством полезных идей и приемов, которые вынесли из своего многолетнего опыта. Авторы надеются, что книга станет источником вдохновения и руководством к действию для многих профессиональных программистов.

Билл де Ора , Майкл Хайгард , Нил Форд

Программирование, программы, базы данных / Базы данных / Программирование / Книги по IT