Как объявить тип значения в CIL: `.class value` или просто`.class`?
Я взглянул на C# struct FooStruct
в ILDASM, и видели следующее:
ILDASM здесь отображает два разных объявления:
- один начинается с
.class
value
public
(заднее стекло и строка заголовка переднего стекла) - один начинается с просто
.class public
(переднее окно)
И мне интересно, какой синтаксис (если не оба) является правильным для объявления типа значения? Это value
Модификатор строго необходим, или необязателен, или синтаксическая ошибка?
2 ответа
Краткий ответ: определения типа значения требуют только
extends [mscorlib]System.ValueType
;value
атрибут представляется необязательным и не имеет видимого эффекта.
Я предполагаю, что спецификация CLI ( ECMA-335) будет лучшим местом для поиска авторского ответа.
ОБЯЗАТЕЛЬНО определение типа значения должно включать value
атрибут?
Раздел II.10 посвящен определению типов. В частности, подраздел II.10.1.3 гласит:
Семантические атрибуты типа определяют, должны ли быть определены интерфейс, класс или тип значения. ... Если [
interface
] атрибут отсутствует, а определение расширяется (прямо или косвенно)System.ValueType
и определение не дляSystem.Enum
тип значения должен быть определен (§II.13). В противном случае класс должен быть определен (§II.11).
value
атрибут вообще не упоминается во всем разделе.
Вывод: правильное определение типа значения не должно включать value
, Извлечение из System.ValueType
достаточно.
МОЖЕТ определение типа значения включать value
модификатор?
Стандарт CLI также содержит грамматику для ILASM (в разделе VI.C.3). Согласно этой грамматике, существует value
атрибут для .class
определения типов. Я дополнительно искал в стандарте конкретные определения типов значений и нашел следующие примеры:
.class public sequential ansi serializable sealed beforefieldinit System.Double extends System.ValueType …
.class private sealed Rational extends [mscorlib]System.ValueType …
.class
value
sealed public MyClass extends [mscorlib]System.ValueType …
Вывод: А value
атрибут может быть включен в определение типа значения.
И что value
атрибут значит?
Я попытался скомпилировать эти три определения типа IL в сборку:
.class public sealed … A extends [mscorlib]System.ValueType { … }
.class value public sealed … B extends [mscorlib]System.ValueType { … }
.class value public sealed … C extends [mscorlib]System.Object { … } // !!!
Не было ошибки компиляции, хотя value
Атрибут используется в объявлении ссылочного типа (см. последнюю строку). Просмотр полученной сборки с помощью обозревателя объектов Visual Studio 2012 показывает два типа значений (struct
) A
а также B
и один ссылочный тип (class
) C
,
Спекуляция: наличие value
Атрибут никак не влияет на определение типа. Он существует только как потенциальная помощь людям в определении определений типов значений.
Эта великая книга содержит простой ответ: когда вы предоставляете extends
пункт тогда value
флаг игнорируется, но если вы не предоставитеextends
и использовать value
тогда ilasm объявит данный тип как тип значения.
Другими словами value
был введен как синтаксический сахар, чтобы быстро объявить тип значения.