代码非常自我解释。我预计当我创建a1
和b1
时,我创建了两个包含相同文本的不同字符串实例。所以我认为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
答案 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";
上查看此内容
答案 2 :(得分:1)
编译器优化了这种情况,并为它们提供了对字符串的相同引用。 C#中的字符串是不可变的吗?
答案 3 :(得分:1)
编译器优化。就这么简单。