说我有一个简单的(最简单的?)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图像中的字符串文字两次。这对我来说很惊讶。我的印象是字符串文字是共享的,因此它只会出现在图像中一次。有谁能解释一下?也许反射元数据需要第二个字符串副本?
答案 0 :(得分:12)
ECMA-335 CLI specification对此有所了解。在IL中,C#const
被声明为static literal
字段。从第I.8.6.1.2节(强调我的):
literal 约束承诺该位置的值实际上是固定值 内置类型。该值被指定为约束的一部分。 编译器是 需要用其值替换所有对该位置的引用,因此需要VES 不需要为该位置分配空间。这种约束虽然在逻辑上适用于 任何位置,只能放置在复合类型的静态字段上。 是的字段 如此标记不允许从CIL引用(它们应在其中列出 编译时的常量值),但可以使用反射和工具 直接处理元数据。
因此编译器获取常量值并在整个代码中替换它。不允许引用常量存储。它从那里做的是它对任何其他文字字符串的作用。它在元数据表中为它提供了一个插槽,并使用ldstr
操作码来加载字符串。因此,值在程序集中出现两次。一旦进入常量的存储位置,就不能被兼容的编译器引用。还有一次在元数据表中。