Книга: ЯЗЫК ПРОГРАММИРОВАНИЯ С# 2005 И ПЛАТФОРМА .NET 2.0. 3-е издание

Снова о создании объектных образов, восстановлении значений и System.Object

Снова о создании объектных образов, восстановлении значений и System.Object

Чтобы понять, в чем заключаются преимущества использования обобщений, следует выяснить, какие проблемы возникают у программиста без их использования. Вы должны помнить из главы 3, что платформа .NET поддерживает автоматическое преобразование объектов стека и динамической памяти с помощью операций создания объектного образа и восстановления из объектного образа. На первый взгляд, эта возможность кажется не слишком полезной и имеющей, скорее, теоретический, чем практический интерес. Но на самом деле возможность создания объектного образа и восстановления из объектного образа очень полезна тем, что она позволяет интерпретировать все, как System.Object, оставив все заботы о распределении памяти на усмотрение CLR.

Чтобы рассмотреть особенности процесса создания объектного образа, предположим, что мы создали System.Collections.ArrayList для хранения числовых (т.е. размещаемых в стеке) данных. Напомним, что все члены ArrayList обладают прототипами для получения и возвращения типов System.Object. Но вместо того, чтобы заставлять программиста вручную вкладывать размещенное в стеке целое число в соответствующую объектную оболочку, среда выполнения делает это автоматически с помощью операции создания объектного образа.

static void Main(string[] args) {
 // При передаче данных члену, требующему объект, для
 // характеризуемых значениями типов автоматически создается
 // объектный образ.
 ArrayList myInts = new ArrayList();
 myInts.Add(10);
 Console.ReadLine();
}

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

static void Main(string[] args) {
 …
 // Значение восстанавливается… и снова становится объектом!
 Console.WriteLine("Значение вашего int: {0}", (int)myInts[0]);
 Console.ReadLine();
}

Для представления операции создания объектного образа в терминах CIL компилятор C# использует блок box. Точно так же операция восстановления из объектного образа преобразуется в CIL-блок unbox. Вот соответствующий CIL-код для показанного выше метода Main() (этот код можно увидеть с помощью ildasm.exe).

.method private hidebysig static void Main(string[] args) cil managed {
 …
 box [mscorlib]System.Int32
 callvirt instance int32 [mscorlib] System.Collections.ArrayList::Add(object)
 pop
 ldstr "Значение вашего int: {0}"
 ldloc.0
 ldc.i4.0
 callvirt instance object [mscorlib] System.Collections.ArrayList::get_Item(int32)
 unbox [mscorlib]System.Int32
ldind.i4
 box [mscorlib]System.Int32
call void [mscorlib]System.Console::WriteLine(string, object)
 …
}

Обратите внимание на то. что перед обращением к ArrayList.Add() размещенное в стеке значение System.Int32 преобразуется в объект, чтобы передать требуемый System.Object. Также заметьте, что при чтении из ArrayList с помощью индексатора типа (что отображается в скрытый метод get_Item()) объект System.Object восстанавливается в System.Int32 только для того, чтобы снова стать объектным образом при передаче методу Console.WriteLine().

Оглавление книги


Генерация: 1.679. Запросов К БД/Cache: 3 / 1
поделиться
Вверх Вниз