Бокс/распаковка - только типы значений? Ref.types - кастинг?
Вопрос
Из MSDN я прочитал, что бокс/распаковка предназначено для лечения ценность типы как объекты. Но когда я читаю о ArrayList, он читает, что он также делает бокс. Так что я довольно смущен, поскольку ArrayList содержит значение и типы ссылок в качестве объектов. Кроме того, следующее не распаковка с точки зрения терминологии, это просто кастинг?
ArrayList a=new ArrayList();
a.Add(someClass);
someClass x=(someClass)a[0];
Решение
ArrayList
Выполняет бокс для типов значений, но не ссылочных типов. Или скорее, ArrayList
Сам сам не делает бокс - компилятор делает. Например:
ArrayList list = new ArrayList();
list.Add(5);
эффективно
ArrayList list = new ArrayList();
object boxed = 5; // Perform boxing from value type type
list.Add(boxed);
Ваш пример действительно просто кастинг - конверсия ссылки, а не преобразование распаковки. Значение типа ссылки не нужно быть в коробке для хранения в ArrayList
- Это уже ссылка.
Опять же, это верно для бокса в целом, и не специфично для ArrayList
. Анкет Бокс - это просто способ использования значения типа значения, где вы В самом деле Хочу ссылки ... ссылка должна быть на объект, поэтому CLR создает объект для обертывания значения типа значения, и возвращает ссылку на эту обертку («Box», хранящий значение).
Другие советы
Бокс/распаковка - это особенность языка и времени выполнения, а не функция ArrayList
. Анкет Свободно говорить, это преобразование типа значения из/в Object
тип, и с тех пор ArrayList
принимает в Object
S, любые типы значений, которые вы проходите box
IL Инструкция.
Более конкретно, бокс/разбивка включает в себя создание или изучение нового объекта и копирование данных типа значения из стека в кучу (или наоборот). Это довольно дорого, и вы хотели бы избежать этого, если это возможно.
В случае эталонных типов код бокса обычно не генерируется; Любые unbox
Инструкция, которая работает на эталонном типе, является, кроме того, просто игнорируется.
Я нахожу полезным думать о типах значений как о том, чтобы быть вне системы типа класса, но рассматривать каждый тип значения как имеющий невидимый соответствующий эталонный тип, полученный из Valuetype (который, в свою очередь, вытекает из объекта), который по существу ведет себя как класс с одинаковыми членами Как Foo, но поддерживает расширение отбрасывает и из реального типа значения.
Если тип значения передается в код, который ожидает производного объекта, он будет привлечен к соответствующему невидимому эталонному типу; Если объект этого эталонного типа назначен переменной типа значения, он будет отброшен.
Кстати, если бы у меня были мои дробиры, был бы какой -то способ указать, что следует использовать что -то другое, чем метод каста по умолчанию, но такая особенность не существует.