Вызов GetType()
для поля типа значения этого типа значения. Перемещая тип значения в кучу, вы получаете ссылочный тип, который теперь имеет указатель на тип этого объекта.
Если вы хотите избежать бокса, вы можете вызвать GetTypeCode
, который возвращает перечисление, указывающее тип типа значения без его упаковки.
Вот пример, показывающий происходящий бокс:
C #:
class Program
{
static void Main()
{
34.GetType();
}
}
IL для Main()
:
.method private hidebysig static void Main() cil managed
{
.entrypoint
.maxstack 8
L_0000: ldc.i4.s 0x22
L_0002: box int32
L_0007: call instance class [mscorlib]System.Type [mscorlib]System.Object::GetType()
L_000c: pop
L_000d: ret
}
Редактировать: Чтобы показать, что делает компилятор, давайте изменим тип литерала следующим образом:
class Program
{
static void Main()
{
34L.GetType();
}
}
Добавляя "L"
после литерала, я сообщаю компилятору, что я хочу, чтобы этот литерал был преобразован в System.Int64
. Компилятор видит это, и когда он выдает инструкцию box
, он выглядит так:
.method private hidebysig static void Main() cil managed
{
.entrypoint
.maxstack 8
L_0000: ldc.i4.s 0x22
L_0002: conv.i8
L_0003: box int64
L_0008: call instance class [mscorlib]System.Type [mscorlib]System.Object::GetType()
L_000d: pop
L_000e: ret
}
Как вы можете видеть, компилятор проделал тяжелую работу по определению правильных команд, которые должны быть отправлены, после этого он должен выполнить CLR.