Как мы можем назначить целое число объекту в .NET?
Типы ссылок выводятся из System.Object, а типы значений – из System.ValueType.
Итак, как это возможно?
Если вы посмотрите на System.ValueType
, это также происходит из System.Object
Также смотрите, как значения ValueTypes получают из Object (ReferenceType) и по-прежнему являются ValueTypes
Термин «бокс» очень непрозрачен, но легко визуализировать то, что на самом деле происходит, используя отладчик. Напишите небольшое консольное приложение:
using System; namespace ConsoleApplication1 { class Program { static void Main(string[] args) { int value = 42; object obj = value; } // < == Breakpoint here } }
Установите точку останова, где указано, и нажмите F5. Когда точка останова попадает, используйте Debug + Windows + Memory + Memory 1. В поле Address введите «obj». Вы получите шестнадцатеричный дамп содержимого памяти объекта. Щелкните правой кнопкой мыши окно и выберите «4-байтное целое число», лучший способ визуализировать объект в этом случае. Вы увидите что-то похожее на это:
0x01CBF6BC 6e1a2d34 0000002a
Интересными здесь являются 0x01CBF6BC, это адрес объекта на сборке мусора. Следующий шестнадцатеричный номер, 6e1a2d34 - это так называемый «дескриптор типа», также известный как «указатель таблицы методов». Это «cookie», который идентифицирует тип объекта. System.Int32 в этом случае. Очень важно, что он будет использоваться позже, когда объект будет распакован обратно в Int32, чтобы убедиться, что значение в штучной упаковке является целым числом.
Следующее значение, которое вы видите, 0000002a, является значением объекта в штучной упаковке. Вы можете использовать калькулятор Windows в режиме программирования, чтобы преобразовать обратно в десятичную, это 42.
Поэкспериментируйте с этим, используя разные значения и различные типы, чтобы увидеть, как он влияет на объект в штучной упаковке. Вы можете изменить шестнадцатеричный код и посмотреть, какой эффект он имеет на значение obj, отображаемое отладчиком.
Шестнадцатеричный дамп, который я дал вам, был для 4-байтового бокс-значения, бокс в два раза займет 8 байт. Бокс структуры будет больше байт. Там также есть часть заголовка объекта, который вы не видите, так называемый syncblock, расположенный по адресу - 4. Попробуйте оператор блокировки, чтобы увидеть, что это изменение.
Это делается путем boxing
и unboxing
. Для получения дополнительной информации см. Следующие ссылки:
Бокс и Unboxing (Руководство по программированию на C #)
Бокс и Unboxing типов значений: что вам нужно знать?
В чем разница между боксом / распаковкой и типом литья?
Бокс и Unboxing :
Бокс – это процесс преобразования типа значения в объект типа или любого типа интерфейса, реализованного этим типом значения. Когда CLR вводит тип значения, он переносит значение внутри объекта System.Object и сохраняет его в управляемой куче. Unboxing извлекает тип значения из объекта.
Вы боксируете целое число в объекте.
То есть создается объект, который обертывает (или помещает ) целое число. Как будто что-то в коробке в реальной жизни.
Попробуйте этот метод:
object ob; int i=10; ob=i;//(boxing) int b; b=(int)ob;//(unboxing)
-object ob; int i=10; ob=i;//(boxing) int b; b=(int)ob;//(unboxing)
Вы должны прочитать о боксе и распаковке в c #, которые должны сказать вам, как / почему.
Эта ссылка имеет отличное объяснение и объясняет вопрос о вопросе типа ссылки и значения, о котором вы спрашиваете:
http://www.dijksterhuis.org/exploring-boxing/
Бокс так же просто кладет базовый тип в обертку (превращая его в полностью раздутый объект) и распаковывает этот обернутый объект и преобразует его обратно в более простой тип. Чтобы сделать управляемую память в боксе, необходимо выделить в куче, ссылки необходимо обновить, а содержимое типа значения нужно скопировать.
int в .NET имеет базовый объект типа Integer и неявное преобразование.
System.ValueType также выводится из System.Object, поэтому:
См. Иерархию наследования:
http://msdn.microsoft.com/en-us/library/system.valuetype.aspx