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

本文关键字:两次 字符串 常量 Net | 更新日期: 2023-09-27 18:33:27

假设我有一个简单的(最简单的?(C# 程序:

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

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

如果我将代码重构为:

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

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

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

ECMA-335 CLI 规范对此进行了一些说明。C# const在 IL 中声明为static literal字段。摘自第一.8.6.1.2节(强调我的(:

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

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