Спецификация CLR по боксу - PullRequest
3 голосов
/ 05 октября 2011

Я сейчас читаю спецификацию CLR . У меня возникли некоторые проблемы с пониманием раздела «I 8.2.4. Упаковка и распаковка значений».

1. Когда можно использовать коробочные типы?

С одной стороны это гласит:

Для каждого типа значения CTS определяет соответствующий ссылочный тип, называемый упакованным типом. [...] Представление значения коробочный тип (коробочное значение) - это место, где может храниться значение типа значения. Тип в штучной упаковке является Тип объекта и в штучной упаковке значение является объектом.

Прямоугольный тип не может быть напрямую указан по имени, поэтому никакая поле или локальная переменная не могут быть указаны в штучной упаковке. type. Ближайшим именованным базовым классом к перечисляемому в штучной форме типом значения является System.Enum; для всех других типов значений это System.ValueType. Поля, типизированные System.ValueType, могут содержать только нулевое значение или экземпляр тип значения в штучной упаковке. Локали, набранные System.Enum, могут содержать только нулевое значение или экземпляр в штучной упаковке. тип перечисления.

Значит ли это, что у меня могут быть свойства / методы, которые используют строго типизированные типы значений в штучной упаковке, или это просто упущение в спецификации? Если да, то почему я могу иметь свойства, но не поля?

С другой стороны, C ++ / CLI, кажется, поддерживает коробочные типы значений даже в локальных переменных, использующих MyStruct^ , но, похоже, странно ведет себя с коробочными примитивными типами (System.Int32^) . Но я не уверен, какая часть этого является магией компилятора C ++ / CLI (вместо нее могут использоваться теговые Object переменные), а какая часть обрабатывается CLR.

Спецификация дополнительно гласит:

CLS Правило 3. Типы в штучной упаковке не соответствуют CLS. [Примечание: вместо упакованных типов используйте System.Object, System.ValueType или System.Enum, в зависимости от ситуации.

Кажется, это подразумевает, что строго типизированные типы значений в штучной упаковке могут быть частью открытого интерфейса типа. Но не должен использоваться для соответствия CLS (что понятно, так как большинство языков их не поддерживают).

Так, где можно использовать строго типизированный тип значения в штучной упаковке? И почему его можно использовать в тех местах, а не в других?

2. Бокс справочных типов

В спецификации также упоминаются типы ссылок на бокс:

Тип может быть упакован в одно из следующих значений:

[...]

  • Ссылочный тип (включая классы, массивы, делегаты и экземпляры универсальных классов), исключая управляемые указатели / byrefs (§8.2.1.1)

  • Универсальный параметр (для определения универсального типа или определения универсального метода) [Примечание: Бокс и распаковка универсальных аргументов увеличивает производительность CLI. Сдержанный. Префикс может повысить производительность при виртуальной диспетчеризации для метода, определенного типом значения, избегая бокс тип значения. конечная нота]

Является ли бокс ссылочного типа запретным? Разрешение ссылочных типов бокса полезно для общих параметров, когда вы не знаете, является ли что-то значением или ссылочным типом. Так что я предполагаю, что бокс ссылочного типа разрешен для согласованности с общими параметрами, представляющими ссылочный тип.

3. Что означает интерфейс, определяемый для типа?

И, наконец, у меня возникли проблемы с пониманием следующего абзаца:

Интерфейсы и наследование определены только для ссылочных типов. Таким образом, в то время как определение типа значения (§8.9.7) может указать оба интерфейса, которые должны быть реализованы типом значения и классом (System.ValueType или System.Enum), от которого он наследуется, они применяются только к коробочным значениям.

Что означает интерфейс, определяемый для типа?Насколько я понимаю, приведение к интерфейсам / базовым классам блокирует значение, но вы все равно можете вызывать методы, определенные в таком интерфейсе / классе, в распакованном виде с помощью ограниченных виртуальных вызовов.(virtcall с префиксом ограничения)

1 Ответ

4 голосов
/ 05 октября 2011

Да, язык C ++ / CLI позволяет объявлять строго типизированные типы коробочных значений:

public ref class Class1
{
public:
    int^ boxedInt;
    Class1() { boxedInt = 42; }
};

Он соблюдает спецификацию CLI, однако поле boxedInt имеет тип ValueType в метаданных.Он запоминает и проверяет упакованный тип с атрибутами modOpt:

field boxedInt: public class System.ValueType modopt(System.Int32) modopt(System.Runtime.CompilerServices.IsBoxed)

То же самое возможно в C #, за исключением того, что компилятор проверяет, что только значения int присвоены полю.Просто объявите поле как ValueType.В противном случае это не имеет практического значения.

...