Семантика присваивания.
Преобразования между ссылочными и значимыми типами
Цель и источник ссылочного типа. Здесь имеет место семантика ссылочного присваивания. В этом случае значениями источника и цели являются ссылки на объекты, хранящиеся в памяти («куче»). При ссылочном присваивании цель разрывает связь с тем объектом, на который она ссылалась до присваивания, и становится ссылкой на объект, связанный с источником. Результат ссылочного присваивания двоякий. Объект… Читать ещё >
Семантика присваивания. Преобразования между ссылочными и значимыми типами (реферат, курсовая, диплом, контрольная)
Рассматривая семантику присваивания и передачи аргументов, мы обошли молчанием один важный вопрос. Будем называть целью левую часть оператора присваивания, а также формальный аргумент при передаче аргументов в процедуру или функцию. Будем называть источником правую часть оператора присваивания, а также фактический аргумент при передаче аргументов в процедуру или функцию. Поскольку источник и цель могут быть как значимого, так и ссылочного типа, то возможны четыре различные комбинации. Рассмотрим их подробнее.
- · Цель и источник значимого типа. Здесь наличествует семантика значимого присваивания. В этом случае источник и цель имеют собственную память для хранения значений. Значения источника заменяют значения соответствующих полей цели. Источник ицель после этого продолжают жить независимо. У них своя память, хранящая после присваивания одинаковые значения.
- · Цель и источник ссылочного типа. Здесь имеет место семантика ссылочного присваивания. В этом случае значениями источника и цели являются ссылки на объекты, хранящиеся в памяти («куче»). При ссылочном присваивании цель разрывает связь с тем объектом, на который она ссылалась до присваивания, и становится ссылкой на объект, связанный с источником. Результат ссылочного присваивания двоякий. Объект, на который ссылалась цель, теряет одну из своих ссылок и может стать висячим, так что его дальнейшую судьбу определит сборщик мусора. С объектом в памяти, на который ссылался источник, теперь связываются, по меньшей мере, две ссылки, рассматриваемые как различные имена одного объекта. Ссылочное присваивание приводит к созданию псевдонимов — к появлению разных имен у одного объекта. Особо следует учитывать ситуацию, когда цель и/или источник имеет значение void. Если такое значение имеет источник, то в результате присваивания цель получает это значение и более не ссылается ни на какой объект. Если же цель имела значение void, а источник — нет, то в результате присваивания ранее «висячая» цель становится ссылкой на объект, связанный с источником.
- · Цель ссылочного типа, источник значимого типа. В этом случае «на лету» значимый тип преобразуется в ссылочный. Как обеспечивается двойственность существования значимого и ссылочного типа — переменной и объекта? Ответ прост: за счет специальных, эффективно реализованных операций, преобразующих переменную значимого типа в объект и обратно. Операция «упаковать «(boxing) выполняется автоматически и неявно в тот момент, когда по контексту требуется объект, а не переменная. Например, при вызове процедуры WhoIsWho требуется, чтобы аргумент any был объектом. Если фактический аргумент является переменной значимого типа, то автоматически выполняется операция «упаковать «. При ее выполнении создается настоящий объект, хранящий значение переменной. Можно считать, что происходит упаковка переменной в объект. Необходимость в упаковке возникает достаточно часто. Примером может служить и процедура консольного вывода WriteLine класса Console, которой требуются объекты, а передаются зачастую переменные значимого типа.
- · Цель значимого типа, источник ссылочного типа. В этом случае «на лету» ссылочный тип преобразуется в значимый. Операция «распаковать «(unboxing) выполняет обратную операцию, — она «сдирает» объектную упаковку и извлекает хранимое значение. Заметьте, операция «распаковать «не является обратной к операции «упаковать «в строгом смысле этого слова. Оператор obj = x корректен, но выполняемый следом оператор x = obj приведет к ошибке. Недостаточно, чтобы хранимое значение в упакованном объекте точно совпадало по типу с переменной, которой присваивается объект. Необходимо явно заданное преобразование к нужному типу.
Операции «упаковать» и «распаковать» (boxing и unboxing).
Примеры В нашем следующем примере демонстрируется применение обеих операций — упаковки и распаковки. Поскольку формальный аргумент процедуры Back принадлежит классу Object, то при передаче фактического аргумента значимого типа происходит упаковка значения в объект. Этот объект и возвращается процедурой. Его динамический тип определяется тем объектом памяти, на который указывает ссылка. Когда возвращаемый результат присваивается переменной значимого типа, то, несмотря на совпадение типа переменной с динамическим типом объекта, необходимо выполнить распаковку, «содрать» объектную упаковку и вернуть непосредственное значение. Вот как выглядит процедура Back и тестирующая ее процедура BackTest из класса Testing:
/// Возвращает переданный ему аргумент.
/// Фактический аргумент может иметь произвольный тип.
/// Возвращается всегда объект класса object.
/// Клиент, вызывающий метод, должен при необходимости.
/// задать явное преобразование получаемого результата.
/// Допустим любой аргумент.
object Back (object any).
{.
return (any);
}.
/// Неявное преобразование аргумента в тип object.
/// Явное приведение типа результата.
public void BackTest ().
{.
ux = (uint)Back (ux);
WhoIsWho («ux», ux);
s1 = (string)Back (s);
WhoIsWho («s1», s1);
x =(int)(uint)Back (ux);
WhoIsWho («x», x);
y = (float)(double)Back (11 + 5.55 + 5.5f);
WhoIsWho («y», y);
}.
Обратите внимание, что если значимый тип в левой части оператора присваивания не совпадает с динамическим типом объекта, то могут потребоваться две операции приведения. Вначале нужно распаковать значение, а затем привести его к нужному типу, что и происходит в двух последних операторах присваивания. Приведу результаты вывода на консоль, полученные при вызове процедуры BackTest в процедуре Main.
Вывод на печать результатов теста BackTest.
Две двойственные операции «упаковать «и «распаковать «позволяют, в зависимости от контекста, рассматривать значимые типы как ссылочные, переменные как объекты, и наоборот.
Размещено на Аllbest.ru.