两个不同的“字符串”是同一个对象实例?

时间:2012-05-28 04:39:31

标签: c# string reference equality

代码非常自我解释。我预计当我创建a1b1时,我创建了两个包含相同文本的不同字符串实例。所以我认为a1 == b1是真的,但object.ReferenceEquals(a1,b1)会是假的,但事实并非如此。为什么呢?

//make two seemingly different string instances
string a1 = "test";
string b1 = "test";         
Console.WriteLine(object.ReferenceEquals(a1, b1)); // prints True. why?

//explicitly "recreating" b2
string a2 = "test";
string b2 = "tes";
b2 += "t";    
Console.WriteLine(object.ReferenceEquals(a2, b2)); // prints False

//explicitly using new string constructor
string a3 = new string("test".ToCharArray());
string b3 = new string("test".ToCharArray());    
Console.WriteLine(object.ReferenceEquals(a3, b3)); // prints False

4 个答案:

答案 0 :(得分:20)

编译器将文字字符串对象合并为单个实例。这实际上是required by the specification

  

每个字符串文字不一定会产生新的字符串实例。当两个或多个根据字符串相等运算符(第7.9.7节)等效的字符串文字出现在同一个程序集中时,这些字符串文字引用相同的字符串实例。

答案 1 :(得分:8)

编译器优化为if字符串文字与“==”运算符相等而不是创建新实例并且都引用相同的实例...所以,这就是你问题的第一部分的原因回答是真的。

虽然string是引用类型,但是定义了相等运算符(==和!=)来比较字符串对象的值,而不是引用。这使得对字符串相等性的测试更加直观。例如:

string a = "hello";
string b = "h";
// Append to contents of 'b'
b += "ello";
Console.WriteLine(a == b);
Console.WriteLine((object)a == (object)b);

这显示“True”然后显示“False”,因为字符串的内容是等效的,但a和b不引用相同的字符串实例。

+运算符连接字符串:

string a = "good " + "morning";

这会创建一个包含“早上好”的字符串对象。

字符串是不可变的 - 创建对象后无法更改字符串对象的内容,尽管语法使其看起来好像可以执行此操作。例如,当您编写此代码时,编译器实际上会创建一个新的字符串对象来保存新的字符序列,并将该新对象分配给b。然后字符串“h”有资格进行垃圾收集。

string b = "h";
b += "ello";

要获得更多参考,请在msdnthis

上查看此内容

答案 2 :(得分:1)

编译器优化了这种情况,并为它们提供了对字符串的相同引用。 C#中的字符串是不可变的吗?

答案 3 :(得分:1)

编译器优化。就这么简单。