CLR是否对字符串常量进行内部化?

3
最近我一直在了解字符串内部池的工作原理。然而,我还没有找到这个问题的答案。
如果我声明一个常量字符串变量,比如const string STR = "foo";,这个字符串也会被添加到内部池中吗?

1
请区分STR和"foo"。STR是一个对象引用,由于它是常量,因此不再出现在方法体中,而是直接编译进去。"foo"是一个对象,就像其他任何普通字面值一样,并且会进行内部优化。编译器完成后,类似于var s = STR;这样的语句与var s = "foo";完全等效。 - undefined
2个回答

4

为了澄清事情... CLR与字符串驻留无关。驻留是一个编译时概念,而CLR中的 R 表示运行时。

此外,字符串变量不会被驻留。字符串 字面值 会被驻留。字面值是指右侧的内容,例如:

var variable = "This is a literal.";

当编译器注意到您的代码中有字符串文字时,它必须将其添加到嵌入在程序集中的资源表中。添加时,它会检查它是否已经存在,如果存在,则只使用现有条目。一旦编译完成,整个表格将被发射到程序集中,在运行时可以由您的代码读取。


这是我见过的最简洁清晰的解释方式。那么,编译器是否会添加声明为常量的字符串字面值呢?此外,我读到过关于国际化表(intern table)作用域限定在CLR,并且在不同应用程序之间共享。这不正确吗? - undefined
1
资源表嵌入在程序集(DLL)中。因此,每个DLL都必须有自己的副本。如果没有这样做,你将无法单独分发它们。 - undefined
这是有道理的。在string.Intern文档中令人困惑的部分在于性能部分提到CLR甚至可以在您的应用程序终止后仍然保留intern表。 - undefined

2

你可以找到:

const string STR = "foo";

string internedFoo = String.IsInterned("foo");    
if (internedFoo != null)  // yes it is !

无论你使用哪个版本的框架,答案都是肯定的,但具体实现取决于不同的情况。并且存在一种模糊设置可以关闭字符串驻留。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接