【问题标题】:CIL - How do I use a public static literal field?CIL - 如何使用公共静态文字字段?
【发布时间】:2014-11-24 02:58:02
【问题描述】:

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

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);

    }
}

Y 使用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?

【问题讨论】:

  • 这是const 字段的问题——它们在运行时不会“存在”任何地方,除了它们被使用的地方。请参阅this、this 和 this。
  • @JonathonReinhart 如果是这样,monodis是如何重现声明b的源代码的?
  • 它仍然嵌入在程序集中。因为它是public,其他代码可能会链接到它,并使用该文字。我对 IL 级别的 const 不是很熟悉,但我相信您所看到的是由于这些链接中描述的 const 的实现。

标签: c# mono cil ilasm


【解决方案1】:

从 C# 的角度来看,您已经有了 cmets-as-answers,但 CIL 规范更合适,也更明确:

I.8.6.1.2 位置签名

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

所以,不,根本没有办法直接引用该字段,也不应该这样做。

【讨论】:

  • 好吧,所以...我正在构建一个编译器,我目前正在生成 CIL 代码。如果我保证不会重新分配常量值,我是否可以在没有文字值的情况下声明我的常量,以使我的代码生成更易于理解?另外,我会接受你的回答,这是我试图理解的。
  • @EdwinA.GonzálezUrzua 如果我理解正确的话,您可以将其设为 initonly(相当于 C# 的 readonly)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-03-21
  • 2023-03-22
  • 2016-05-08
  • 2015-04-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多