如何在 CIL 中声明值类型:`.class value` 还是只是 `.class`?

sta*_*ica 5 syntax cil definition value-type ilasm

我查看了ILDASMstruct FooStruct中的C# ,并看到了以下内容:

在此输入图像描述

ILDASM 此处显示两个不同的声明:

  • 一个以(后窗和前窗标题栏)开头.class value public
  • 一个以.class public(前窗)开头

我想知道哪种语法(如果不是两种)是声明值类型的正确语法?修饰符是value严格必需的、可选的还是语法错误?

sta*_*ica 4

\n

简短回答:值类型定义只需要extends [mscorlib]System.ValueType; 该value属性似乎是可选的并且没有明显的效果。

\n
\n\n

我认为 CLI 规范 ( ECMA-335 ) 将是寻找权威答案的最佳位置。

\n\n

值类型定义必须包含value属性吗?

\n\n

II.10 节涉及定义类型。更具体地说,第 II.10.1.3 小节规定:

\n\n
\n

类型语义属性指定是否应定义接口、类或值类型。\xe2\x80\xa6 如果 [the interface] 属性不存在并且定义扩展了 \n (直接或间接)System.ValueType,并且定义不是 for System.Enum,则应定义值类型 (\xc2\xa7II.13)。否则,应定义一个类(\xc2\xa7II.11)。

\n
\n\n

value整个部分根本没有提到该属性。

\n\n

结论:正确的值类型定义不必包含value. 派生自就System.ValueType足够了。

\n\n

值类型定义可以包含value修饰符吗?

\n\n

CLI 标准还包含 ILASM 语法(在第 VI.C.3 节中)。根据该语法,存在类型定义value的属性.class。我还搜索了具体值类型定义的标准,并找到了以下示例:

\n\n
    \n
  • .class public sequential ansi serializable sealed beforefieldinit System.Double extends System.ValueType \xe2\x80\xa6
  • \n
  • .class private sealed Rational extends [mscorlib]System.ValueType \xe2\x80\xa6
  • \n
  • .class value sealed public MyClass extends [mscorlib]System.ValueType \xe2\x80\xa6
  • \n
\n\n

结论:属性value可以包含在值类型定义中。

\n\n

该属性的含义是什么value

\n\n

我尝试将这三个 IL 类型定义编译成程序集:

\n\n
.class       public sealed \xe2\x80\xa6 A extends [mscorlib]System.ValueType { \xe2\x80\xa6 }\n.class value public sealed \xe2\x80\xa6 B extends [mscorlib]System.ValueType { \xe2\x80\xa6 }\n.class value public sealed \xe2\x80\xa6 C extends [mscorlib]System.Object    { \xe2\x80\xa6 }  // !!!\n
Run Code Online (Sandbox Code Playgroud)\n\n

value即使在引用类型声明中使用该属性(请参见最后一行),也没有编译错误。使用 Visual Studio 2012 的对象浏览器查看生成的程序集,会发现两种值类型 ( struct)AB,以及一种引用类型 ( class) C

\n\n

推测:属性的存在value对类型定义没有任何影响。它只是作为人类发现值类型定义的潜在帮助。

\n