Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
CSBasicCourse2ndedPodbelsky / CSBasicCourse2ndedPodbelsky.rtf
Скачиваний:
27
Добавлен:
22.03.2016
Размер:
11.9 Mб
Скачать

15.4. Упаковка и распаковка

Когда значение структурного типа преобразуется к типу object или

приводится к типу того интерфейса, который реализован структурой, выполняется

операция упаковки (boxing). Эта операция выполняется автоматически и не требует

вмешательства программиста.

Упаковкой

"упаковка"

называют процесс явного преобразования из типа

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

которому присваивается значение объекта с типом значения. Возвращаемым

значением при выполнении упаковки служит ссылка на объект кучи.

Обратной операцией является распаковка (unboxing), при которой значение

объекта присваивается переменной с типом значения.

Автоматическая упаковка "упаковка:автоматическая упаковка" выполняется

в тех случаях, когда выполняется допустимое присваивание ссылке на объект

ссылочного типа переменной с типом значения. Так как все классы языка C# имеют

общий базовый класс object , то ссылке типа object можно присвоить значение

структуры. В этом случае выполняется автоматическая упаковка, не требующая

вмешательства программиста. Обратная процедура – распаковка – автоматически не

выполняется. Для распаковки необходимо применять операцию приведения типов.

Сказанное относится не только к присваиванию, но и к передаче параметров и

к возвращаемому методом результату. Рассмотрим статический метод с таким

заголовком:

static object reDouble(object obj)

Метод принимает ссылку на объект типа object и возвращает значение того же

типа. Внешне ничто не препятствует применению в обращении к этому методу в

качестве аргумента ссылки на объект любого типа. Однако, в теле метода

необходимо учитывать конкретный тип аргумента, и формировать возвращаемый

результат в соответствии с этим типом. В следующей программе определена

структура Struct1 с полем x типа double, и метод с приведенным выше заголовком.

// 15_10.cs - структуры, упаковка, распаковк

а

using System;

struct Struct1 // структура

{

double x;

public double X { get { return x; } set { x = value; } }

}

class Program

{

static object reDouble(object obj)

{

If (obj is Struct1)

{

Struct1 st = (Struct1)obj;

st.X = 2 * st.X;

return st;

}

else

Console.WriteLine("Неизвестный тип!");

return obj;

}

static void Main()

{

Struct1 one = new Struct1();

one.X = 4;

Struct1 two = (Struct1)reDouble(one);

Console.WriteLine("one.X={0}; two.X={1}",

one.X, two.X);

Console.WriteLine("(int)reDouble(55)={0}",

(int)reDouble(55));

}

}

Результат выполнения программы:

one.X=4; two.X=8

Неизвестный тип!

(int)reDouble(55)=55

Метод reDouble() обрабатывает только аргументы типа Struct1, хотя ему

можно передать аргумент любого типа. Если аргумент имеет тип Struct1, метод

reDouble() выполняет его распаковку и удваивает значение поля double x. Если тип

аргумента отличен от Struct1, то тип распознаётся как неизвестный и аргумент

возвращается в точку вызова в «упакованном» виде. Для примера в методе Main()

обращение к reDouble() выполнено дважды с аргументами разных типов.

Понимание процедур упаковки и распаковки необходимо для применения

таких библиотечных средств как коллекции. К ним относится класс ArrayList

"класс: ArrayList" (массив-список "массив:массив-список" ) из пространства имён

System.Collections. Объект класса ArrayList во многих случаях «ведёт себя» как

массив. Например, к нему применима индексация. В отличие от массивов,

производных от класса Array, объекты класса ArrayList могут расти в процессе

выполнения программы. Количество их элементов увеличивается, как только в этом

возникает

необходимость,

причём

рост

выполняется

автоматически

без

вмешательства программиста.

Но не всё просто. Рассмотрим объявление такого растущего массива-списка:

using System.Collection;

..

ArrayList dinamo = new ArrayList(3);

В данном примере объявлена ссылка dinamo и ассоциированный с нею объект

класса ArrayList

"класс: ArrayList" . В обращении к конструктору ArrayList()

указан начальный размер массива-списка. Можно предположить, что теперь можно

обращаться к элементам массива-списка, используя индексы со значениями 0, 1, 2.

Однако следующая попытка будет ошибочной:

dinamo [1]=45.3; // ошибка времени исполнения

Даже,

если

в

вызове

конструктора

указан

размер

массива-списка,

первоначально элементов в создаваемом массиве-списке НЕТ! Отличие объекта

класса ArrayList от традиционного массива состоит в том, что в массив-список

элементы должны быть вначале занесены с помощью нестатического метода Add()

"метод: Add()" класса ArrayList.

Заголовок метода: public virtual int Add(object value)

Метод добавляет в конец массива-списка элемент, заданный аргументом.

Возвращаемое значение – порядковый номер (индекс) добавленного элемента

.

Нумерация элементов начинается с нуля.

Так как тип параметра object, то в качестве аргумента можно использовать

значение любого типа. Следовательно, в один массив-список можно помещать

элементы разных типов. Процедура упаковки, необходимая для аргументов с типами

значений, выполняется автоматически. А вот при получении значения элемента

массива-списка нужно явно выполнить распаковку, узнав предварительно какой тип

имеет элемент.

В следующей программе создан массив-список, представляемый ссылкой

ArrayList dynamo. Затем в этот массив-список добавлены элементы со значениями

double, int и PointS, где PointS – пользовательский тип, объявленный в программе

как структура. Текст программы:

// 15_11.cs - структуры и массив-список типа ArrayList

using System;

using System.Collections; // Для ArrayList

class Program

{

static void Main()

{

ArrayList dinamo = new ArrayList();

dinamo.Add(4.8);

dinamo.Add(new PointS());

dinamo.Add(100);

PointS ps = new PointS();

ps.X = 10.2;

dinamo.Add(ps);

dinamo[1] = 1.23;

foreach (object ob in dinamo)

Соседние файлы в папке CSBasicCourse2ndedPodbelsky