C# 4.0 полное руководство - 2011
Шрифт:
Распаковка представляет собой процесс извлечения упакованного значения из объекта. Это делается с помощью явного приведения типа ссылки на объект класса ob j ect к соответствующему типу значения. Попытка распаковать объект в другой тип может привести к ошибке во время выполнения.
Ниже приведен простой пример, демонстрирующий упаковку и распаковку.
// Простой пример упаковки и распаковки.
using System;
class BoxingDemo { static void Main {
int x; object obj ;
X = 10;
obj =
int у = (int)obj; // распаковать значение из объекта, доступного по // ссылке obj, в переменную типа int Console.WriteLine(у);
}
}
В этом примере кода выводится значение 10. Обратите внимание на то, что значение переменной х упаковывается в объект простым его присваиванием переменной obj, ссылающейся на этот объект. А затем это значение извлекается из объекта, доступного по его ссылке obj, и далее приводится к типу int.
Ниже приведен еще один, более интересный пример упаковки. В данном случае значение типа int передается в качестве аргумента методу Sqr , который, в свою очередь, принимает параметр типа object.
// Пример упаковки при передаче значения методу.
using System;
class BoxingDemo { static void Main { int x; x = 10;
Console.WriteLine("Значение x равно: " + x);
// значение переменной x автоматически упаковывается // когда оно передается методу Sqr. х = BoxingDemo.Sqr(х) ;
Console.WriteLine("Значение x в квадрате равно: " + х);
}
static int Sqr(object о) { return (int)о * (int)о;
}
}
Вот к какому результату приводит выполнение этого кода.
Значение х равно: 10
Значение х в квадрате равно: 100
В данном примере значение переменной х автоматически упаковывается при передаче методу Sqr .
Упаковка и распаковка позволяют полностью унифицировать систему типов в С#. Благодаря тому что все типы являются производными от класса object, ссылка на значение любого типа может быть просто присвоена переменной ссылочного типа object, а все остальное возьмут на себя упаковка и распаковка. Более того, методы класса object оказываются доступными всем типам, поскольку они являются производными от этого класса. В качестве примера рассмотрим довольно любопытную программу.
// Благодаря упаковке становится возможным вызов методов по значению! using System;
/
class MethOnValue { static void Main {
Console.WriteLine(10.ToString ) ;
}
}
В результате
Класс object как универсальный тип данных
Если obj ect является базовым классом для всех остальных типов и упаковка значений простых типов происходит автоматически, то класс object можно вполне использовать в качестве "универсального" типа данных. Для примера рассмотрим программу, в которой сначала создается массив типа object, элементам которого затем присваиваются значения различных типов данных.
// Использовать класс object для создания массива "обобщенного" типа.
using System;
class GenericDemo { static void Main {
object[] ga. = new object[10];
// Сохранить целые значения, for (int i=0; i < 3; i++) ga[i] = i;
ga[9] = "Конец";
for(int i = 0; i < ga.Length; i++)
Console.WriteLine("ga[" + i + "]: " + ga[i] + " ");
}
}
Выполнение этой программы приводит к следующему результату.
да [ 0] : 0 да[1] : 1
да
[2] :
2
да[3] :
1.5
да [4] :
2
да[5] :
2.5
да[6] :
Привет
да
[7] :
True
да
[8] :
X
да
[9] :
Конец
Как показывает данный пример, по ссылке на объект класса object можно обращаться к данным любого типа, поскольку в переменной ссылочного типа object допускается хранить ссылку на данные всех остальных типов. Следовательно, в массиве типа object из рассматриваемого здесь примера можно сохранить данные практически любого типа. В развитие этой идеи можно было бы, например, без особого труда создать класс стека со ссылками на объекты класса object. Это позволило бы хранить в стеке данные любого типа.