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

Nei*_*ell 15 c# string optimization

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

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

Jon*_*eet 17

编辑:虽然我强烈怀疑下面的声明适用于所有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;
}
Run Code Online (Sandbox Code Playgroud)

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

编辑:从的Mads和Eric的答复建议,在微软的C#编译器字符串常量和字符串文字通常的处理方式相同-但其他的实现可能会有所不同.


Dar*_*rov 7

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

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


Cod*_*aos 7

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

string s1="A";
string s2="A";
object.ReferenceEquals(s1,s2);  //true
Run Code Online (Sandbox Code Playgroud)