4

我有示例代码。

var charMass = new char[] { 's', 't', 'r' };
string myString = new string(charMass);
string myString2 = new string(charMass);
string myString3 = "str";
string myString4 = "str";

bool bb1 = Object.ReferenceEquals(myString, myString2);
bool bb2 = Object.ReferenceEquals(myString, myString3);
bool bb3 = Object.ReferenceEquals(myString3, myString4);

为什么 bb1 和 bb2 是假的?我知道 equals 必须显示为真,因为它比较值,但是那些字符串的内存分配呢?为什么 myString3 和 myString4 指向堆中的同一个内存块,但 myString 和 myString2 没有?

4

5 回答 5

5

C# 编译器对其进行优化,因此相同的文字指向相同的字符串实例

MSDN

实习生池保存字符串存储。如果将文字字符串常量分配给多个变量,则每个变量都设置为引用实习池中的相同常量,而不是引用具有相同值的多个不同 String 实例。

于 2013-02-21T10:08:31.107 回答
4

我在这里回答你的问题:

http://blogs.msdn.com/b/ericlippert/archive/2009/09/28/string-interning-and-string-empty.aspx

简短的回答是:实习文字字符串既便宜又容易,因此默认情况下完成。实习动态分配的字符串通常会以大量时间为代价节省少量字节,因此不值得为. 如果你想强制实习,你可以自己去做。

于 2013-02-21T15:31:56.530 回答
1

myString并且myString2永远不能彼此(或任何其他字符串)引用相等,因为您显式调用了字符串构造函数,导致每次都创建一个新对象。显然,这个新对象不会与任何其他已经存在的对象引用相等。

myString3并且myString4是引用相等的,因为编译器对字符串进行了实习:在编译时用字符串文字初始化的字符串值最终在运行时成为对同一对象的引用:

公共语言运行时通过维护一个称为实习池的表来保存字符串存储,该表包含对程序中以编程方式声明或创建的每个唯一文字字符串的单个引用。因此,具有特定值的文字字符串的实例在系统中只存在一次。

例如,如果您将相同的文字字符串分配给多个变量,则运行时会从实习池中检索对文字字符串的相同引用并将其分配给每个变量。

于 2013-02-21T10:11:58.890 回答
0

也许编译器以某种方式将其优化"str"为单个文字,然后将其分配给每个变量,当然,字符串是指针,意味着它们都指向同一个地址。

于 2013-02-21T10:09:05.913 回答
0

这是基于框架中String的底层实现。

http://msdn.microsoft.com/en-us/library/system.string.intern.aspx

我看到的方式是,对于 myString 和 myString2,您使用 char[] 创建了它们,并且在创建字符串时在实习生池中没有默认查找。

在 myString3 和 myString4 的情况下,myString3 为 InternPool 添加了价值,而对于 myString4,您只是获得了一个引用,因为它是示例块。

我以前的印象是,在早期版本的框架中,IsIntern 是可选的,并且可以让开发人员使用。看起来不一定是这样

于 2013-02-21T10:13:29.123 回答