Как объявить тип значения в CIL: `.class value` или просто`.class`?

Я взглянул на C# struct FooStruct в ILDASM, и видели следующее:

ILDASM здесь отображает два разных объявления:

  • один начинается с .classvaluepublic (заднее стекло и строка заголовка переднего стекла)
  • один начинается с просто .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 …
  • .classvaluesealed 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 был введен как синтаксический сахар, чтобы быстро объявить тип значения.

Другие вопросы по тегам