C#do字符串文字是否由编译器优化?

C#编译器或.NET CLR是否对字符串文字/常量进行了任何巧妙的内存优化? 我可以发誓我听说过“字符串内化”的概念,所以在程序的任何两位代码中,字面意思“这是一个字符串”实际上是指同一个对象(大概是安全的,字符串是什么一成不变的?)。 我在谷歌上找不到任何有用的参考资料……

我听错了吗? 别担心 – 我的代码中没有用这些信息做任何可怕的事情,只是想更好地了解它的工作原理。

编辑:虽然我强烈怀疑下面的声明适用于所有C#编译器实现,但我不确定它在规范中是否真的有保证。 规范的2.4.4.5节讨论了引用相同字符串实例的文字 ,但没有提到其他常量字符串表达式。 我怀疑这是规范中的一个疏忽 – 我会给Mads和Eric发电子邮件。


它不仅仅是字符串文字。 它是任何字符串常量 。 例如,考虑一下:

public const string X = "X"; public const string Y = "Y"; public const string XY = "XY"; void Foo() { string z = X + Y; } 

编译器意识到这里的连接(对于z )在两个常量字符串之间,因此结果也是一个常量字符串。 因此, z的初始值将与XY的值相同,因为它们是具有相同值的编译时常量。

编辑:Mads和Eric的回复表明,在Microsoft C#编译器中,字符串常量和字符串文字通常以相同的方式处理 – 但其他实现可能会有所不同。

本文很好地解释了字符串实习。 引用:

.NET具有“实习池”的概念。 它基本上只是一组字符串,但它确保每次引用相同的字符串文字时,都会得到对同一字符串的引用。 这可能与语言有关,但在C#和VB.NET中肯定是这样,我会非常惊讶地看到它不适用的语言,因为IL使它很容易做到(可能比失败更容易)实习生文学)。 除了自动实习的文字外,您还可以使用Intern方法手动实习字符串,并使用IsInterned方法检查池中是否已存在具有相同字符序列的实习字符串。 这有点不直观地返回一个字符串而不是一个布尔值 – 如果池中有一个相等的字符串,则返回对该字符串的引用。 否则,返回null。 同样,Intern方法返回对实习字符串的引用 – 如果已经在池中,则传入的字符串,或者新创建的实习字符串,或者已经在池中的相等字符串。

是的,它确实优化了字符串文字。 一个简单的例子,你可以看到:

 string s1="A"; string s2="A"; object.ReferenceEquals(s1,s2); //true