字符串常量在.Net中嵌入两次?

时间:2014-12-05 22:35:16

标签: c# .net

说我有一个简单的(最简单的?)C#程序:

class Program {
    static void Main() {
      System.Console.WriteLine("Hello, world");
    }
}

如果,我编译该代码并查看生成的.exe,我看到" Hello,world" exe图像中的字符串符合预期。

如果我将代码重构为:

class Program {
    const string Greeting = "Hello, world";
    static void Main() {
      System.Console.WriteLine(Greeting);
    }
}

如果我编译该代码并查看生成的.exe,我会看到" Hello,world" exe图像中的字符串文字两次。这对我来说很惊讶。我的印象是字符串文字是共享的,因此它只会出现在图像中一次。有谁能解释一下?也许反射元数据需要第二个字符串副本?

1 个答案:

答案 0 :(得分:12)

ECMA-335 CLI specification对此有所了解。在IL中,C#const被声明为static literal字段。从第I.8.6.1.2节(强调我的):

  

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

因此编译器获取常量值并在整个代码中替换它。不允许引用常量存储。它从那里做的是它对任何其他文字字符串的作用。它在元数据表中为它提供了一个插槽,并使用ldstr操作码来加载字符串。因此,值在程序集中出现两次。一旦进入常量的存储位置,就不能被兼容的编译器引用。还有一次在元数据表中。