【问题标题】:Two different "strings" are the same object instance?两个不同的“字符串”是同一个对象实例?
【发布时间】:2012-05-28 04:39:31
【问题描述】:

代码很容易解释。当我创建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

【问题讨论】:

标签: c# string reference equality


【解决方案1】:

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

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

【讨论】:

  • 参见上面的 V4Vendetta 链接。这是由编译器还是 CLR 发生的?
【解决方案2】:

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

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

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

【讨论】:

  • 这与我的问题无关。
【解决方案3】:

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

【讨论】:

    猜你喜欢
    • 2019-09-29
    • 2020-11-21
    • 2016-01-19
    • 2011-05-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-24
    • 1970-01-01
    相关资源
    最近更新 更多