首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >字符串实例化?

字符串实例化?
EN

Stack Overflow用户
提问于 2010-04-25 07:40:40
回答 6查看 2.4K关注 0票数 8

第二个ReferenceEquals调用返回false。为什么s4中的字符串没有内嵌?(我并不关心StringBuilder相对于字符串连接的优势。)

代码语言:javascript
复制
string s1 = "tom";
string s2 = "tom";


Console.Write(object.ReferenceEquals(s2, s1)); //true

string s3 = "tom";
string s4 = "to";
s4 += "m";

Console.Write(object.ReferenceEquals(s3, s4)); //false

当我执行String.Intern(s4);时,我仍然得到false。

这里,s3和s4都被限制了,但是它们的引用不相等吗?

代码语言:javascript
复制
string s3 = "tom";
string s4 = "to";
s4 += "m";
String.Intern(s4);

Console.WriteLine(s3 == s4); //true
Console.WriteLine(object.ReferenceEquals(s3, s4)); //false
Console.WriteLine(string.IsInterned(s3) != null);  //true (s3 is interned)
Console.WriteLine(string.IsInterned(s4) != null);  //true (s4 is interned)
EN

回答 6

Stack Overflow用户

回答已采纳

发布于 2010-04-25 07:44:27

s4中的字符串被截获。但是,当您执行s4 += "m";时,您已经创建了一个不会被实例化的新字符串,因为它的值不是字符串文字,而是字符串连接操作的结果。因此,s3s4是位于两个不同内存位置的两个不同的string实例。

有关字符串内嵌的更多信息,请查看here,特别是最后一个示例。当您执行String.Intern(s4)时,您实际上是在实例化字符串,但是您仍然没有在这两个实例化字符串之间执行引用相等测试。String.Intern方法返回内部字符串,因此您需要执行以下操作:

代码语言:javascript
复制
string s1 = "tom";
string s2 = "tom";

Console.Write(object.ReferenceEquals(s2, s1)); //true 

string s3 = "tom";
string s4 = "to";
s4 += "m";

Console.Write(object.ReferenceEquals(s3, s4)); //false

string s5 = String.Intern(s4);

Console.Write(object.ReferenceEquals(s3, s5)); //true
票数 17
EN

Stack Overflow用户

发布于 2010-04-25 07:43:31

字符串是不可变的。这意味着它们的内容不能被改变。

在内部执行s4 += "m";时,CLR会将字符串复制到内存中包含原始字符串和附加部分的另一个位置。

参见MSDN string reference

票数 3
EN

Stack Overflow用户

发布于 2010-04-25 08:16:22

首先,到目前为止关于不可变字符串的所有内容都是正确的。但是有一些重要的东西没有写出来。代码

代码语言:javascript
复制
string s1 = "tom";
string s2 = "tom";
Console.Write(object.ReferenceEquals(s2, s1)); //true

显示真正的"True",但仅仅是因为一些小的编译器优化,或者像这里这样,因为CLR忽略了C#编译器属性(参见“通过C#的CLR”一书),只将一个字符串"tom"放在堆中。

其次,您可以使用以下几行代码来修复这种情况:

代码语言:javascript
复制
s3 = String.Intern(s3);
s4 = String.Intern(s4);
Console.Write (object.ReferenceEquals (s3, s4)); //true

函数String.Intern计算字符串的散列代码,并在内部散列表中搜索相同的散列。因为它找到了它,所以它返回对已经存在的String对象的引用。如果该字符串不存在于内部哈希表中,则会复制该字符串并计算哈希值。垃圾收集器不会为字符串释放内存,因为它被哈希表引用。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2706607

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档