CIL - 如何使用公共静态文字字段?

时间:2014-11-24 02:58:02

标签: c# mono cil ilasm

这可能是一个愚蠢的问题,但如果我能做到这一点,我真的很好奇。我写了以下示例程序:

class Test1 {

    public const int b = 8;
    public static int z = 3;

    public static void Main(string[] args){
        const int q = 6;
        Console.WriteLine(q);
        Console.WriteLine(b);
        Console.WriteLine(z);

    }
}

使用mcs对此进行编译,然后使用monodis对生成的exe进行反汇编。获得以下代码:

.field public static literal  int32 b = int32(0x00000008)
.field  public static  int32 z

// method line 2
.method public static hidebysig 
       default void Main (string[] args)  cil managed 
{
    // Method begins at RVA 0x2058
      .entrypoint
      // Code size 23 (0x17)
      .maxstack 8
      IL_0000:  ldc.i4.6 
      IL_0001:  call void class [mscorlib]System.Console::WriteLine(int32)
      IL_0006:  ldc.i4.8 
      IL_0007:  call void class [mscorlib]System.Console::WriteLine(int32)
      IL_000c:  ldsfld int32 Test.Test1::z
      IL_0011:  call void class [mscorlib]System.Console::WriteLine(int32)
      IL_0016:  ret 
} // end of method Test1::Main

我想使用ldsfld加载b的值。如果我将IL_0006更改为ldsfld int32 Test.Test1::b,它将汇编,但是当我运行可执行文件时,我获得了一个删除:

Unhandled Exception:
System.InvalidProgramException: Invalid IL code in Test.Test1:Main 
(string[]): IL_0006: ldsfld    0x04000001


[ERROR] FATAL UNHANDLED EXCEPTION: System.InvalidProgramException: 
Invalid IL code in Test.Test1:Main (string[]): IL_0006: ldsfld    0x04000001

有没有办法使用static literal而不是仅使用ldc

1 个答案:

答案 0 :(得分:6)

您已经从C#视角获得了评论作为答案,但CIL规范更合适也更明确:

  

I.8.6.1.2位置签名

     

文字约束承诺该位置的值实际上是内置类型的固定值。该值被指定为约束的一部分。编译器是   需要用其值替换对该位置的所有引用,因此需要VES   不需要为该位置分配空间。这种约束虽然在逻辑上适用于   任何位置,只能放置在复合类型的静态字段上。 字段   如此标记不允许从CIL引用 (它们应与其内容一致   编译时的常量值),但可以使用反射和工具   直接处理元数据。

所以,不,没有办法直接引用那个字段,并且不应该这样。