Читаем Интернет-журнал "Домашняя лаборатория", 2007 №9 полностью

В нашем следующем примере демонстрируется применение обеих операций — упаковки и распаковки. Поскольку формальный аргумент процедуры Back принадлежит классу Object, то при передаче фактического аргумента значимого типа происходит упаковка значения в объект. Этот объект и возвращается процедурой. Его динамический тип определяется тем объектом памяти, на который указывает ссылка. Когда возвращаемый результат присваивается переменной значимого типа, то, несмотря на совпадение типа переменной с динамическим типом объекта, необходимо выполнить распаковку, "содрать" объектную упаковку и вернуть непосредственное значение. Вот как выглядит процедура Back и тестирующая ее процедура BackTest из класса Testing:

///

/// Возвращает переданный ему аргумент.

/// Фактический аргумент может иметь произвольный тип.

/// Возвращается всегда объект класса object.

/// Клиент, вызывающий метод, должен при необходимости

/// задать явное преобразование получаемого результата ///

///  Допустим любой аргумент

/// 

object Back(object any)

{

      return(any);

}

/// 

/// Неявное преобразование аргумента в тип object

/// Явное приведение типа результата.

///  public void BackTest ()

{

      ux = (uint)Back(их);

      WhoIsWho("uх",uх);

      s1 = (string)Back(s);

      WhoIsWho("s1",s1);

      x =(int) (uint)Back(uх);

      WhoIsWho("x",x);

      у = (float)(double)Back(11 + 5.55 + 5.5f);

      WhoIsWho("y",y);

}

Обратите внимание, что если значимый тип в левой части оператора присваивания не совпадает с динамическим типом объекта, то могут потребоваться две операции приведения. Вначале нужно распаковать значение, а затем привести его к нужному типу, что и происходит в двух последних операторах присваивания. Приведу результаты вывода на консоль, полученные при вызове процедуры

Рис. 3.2.Вывод на печать результатов теста BackTest

Две двойственные операции "упаковать" и ''распаковать'' позволяют, в зависимости от контекста, рассматривать значимые типы как ссылочные, переменные как объекты, и наоборот.

4. Преобразования типов

Преобразования типов. Преобразования внутри арифметического типа. Преобразования строкового типа. Класс Convert и его методы. Проверяемые преобразования. Управление проверкой арифметических преобразований.

Где, как и когда выполняются преобразования типов?

Необходимость в преобразовании типов возникает в выражениях, присваиваниях, замене формальных аргументов метода фактическими.

Если при вычислении выражения операнды операции имеют разные типы, то возникает необходимость приведения их к одному типу. Такая необходимость возникает и тогда, когда операнды имеют один тип, но он несогласован с типом операции. Например, при выполнении сложения операнды типа byte должны быть приведены к типу int, поскольку сложение не определено над байтами. При выполнении присваивания х=е тип источника е и тип цели х должны быть согласованы. Аналогично, при вызове метода также должны быть согласованы типы источника и цели — фактического и формального аргументов.

Преобразования ссылочных типов

Поскольку операции над ссылочными типами не определены (исключением являются строки, но операции над ними, в том числе и присваивание, выполняются как над значимыми типами), то необходимость в них возникает только при присваиваниях и вызовах методов. Семантика таких преобразований рассмотрена в предыдущей лекции 3, где подробно обсуждалась семантика присваивания и совпадающая с ней семантика замены формальных аргументов фактическими. Там же много говорилось о преобразованиях между ссылочными и значимыми типами, выполняемых при этом операциях упаковки значений в объекты и обратной их распаковки.

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

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