Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
CSharp Language Specification.doc
Скачиваний:
13
Добавлен:
26.09.2019
Размер:
4.75 Mб
Скачать

4.3Упаковка и распаковка

Понятие упаковки и распаковки является ключевым в системе типов C#. С помощью данных операций осуществляется связь между типами_значений и ссылочными_типами за счет возможности преобразования любого значения типа_значений к типу object и обратно. С помощью упаковки и распаковки обеспечивается унифицированное представление системы типов, в котором значение любого типа может обрабатываться как объект.

4.3.1Преобразования упаковки

Преобразование упаковки обеспечивает неявное преобразование типа_значений в ссылочный_тип. Предусмотрены следующие преобразования упаковки:

  • из любого типа_значений к типу object;

  • из любого типа_значений к типу System.ValueType;

  • из любого необнуляемого_типа_значений к любому типу_интерфейса, реализованному с помощью типа_значений;

  • из любого обнуляемого_типа к любому типу_интерфейса, реализованному с помощью базового типа для обнуляемого_типа;

  • из любого перечисляемого_типа к типу System.Enum;

  • из любого обнуляемого_типа, базовым для которого является перечисляемый_тип, к типу System.Enum.

Обратите внимание, что если неявное преобразование из параметра типа во время выполнения включает в себя преобразование из типа значений к ссылочному типу, оно будет выполнено как преобразование упаковки (§6.1.10).

Упаковка значения необнуляемого_типа_значений включает в себя выделение экземпляра объекта и копирование этого значения в указанный экземпляр.

Если выполняется упаковка значения null (свойство HasValue имеет значение false) обнуляемого_типа, то при этом создается пустая ссылка. В противном случае возвращается результат развертывания и упаковки базового значения.

Чтобы более наглядно представить процесс упаковки значения необнуляемого_типа_значений, предположим существование универсального класса упаковки, поведение которого могло бы определяться следующим объявлением:

sealed class Box<T>: System.ValueType { T value;

public Box(T t) { value = t; } }

Упаковка значения v типа T будет включать в себя выполнение выражения new Box<T>(v) с последующим возвратом результата в виде значения типа object. Таким образом, операторы

int i = 123; object box = i;

будут соответствовать операторам

int i = 123; object box = new Box<int>(i);

В действительности описанный выше класс упаковки Box<T> не существует, а динамический тип упакованного значения не является типом класса. Упакованное значение типа T имеет динамический тип T. При проверке динамического типа с помощью оператора is возможно использование ссылки на тип T. Например,

int i = 123; object box = i; if (box is int) { Console.Write("Box contains an int"); }

на консоль будет выведена строка «Box contains an int».

Преобразование упаковки подразумевает создание копии упаковываемого значения. В этом заключается отличие от преобразования ссылочного_типа к типу object, при котором значение продолжает хранить ссылку на тот же экземпляр и считается производным значением типа object более низкого уровня. Например, при объявлении

struct Point { public int x, y;

public Point(int x, int y) { this.x = x; this.y = y; } }

в результате выполнения операторов

Point p = new Point(10, 10); object box = p; p.x = 20; Console.Write(((Point)box).x);

на консоль будет выведено значение 10, поскольку при выполнении операции неявной упаковки (осуществляется при присвоении значения p свойству box) происходит копирование значения p. Если вместо Point объявить class, будет выведено значение 20, поскольку в этом случае значения p и box будут содержать ссылки на один и тот же экземпляр.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]