C#中的赋值和创建字符串实例有什么区别?

时间:2013-02-21 10:05:51

标签: c# string heap

我有示例代码。

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必须显示为true,因为它比较了值,但是那些字符串的内存分配呢?为什么myString3和myString4指向堆中的同一块内存但myString和myString2没有?

5 个答案:

答案 0 :(得分:5)

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

MSDN

  

实习池保存了字符串存储空间。 如果您指定文字   字符串常量为几个变量,每个变量都设置为   在实习池中引用相同的常量而不是   引用具有相同的String的几个不同实例   值。

答案 1 :(得分:4)

我在这里回答你的问题:

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

简短的回答是:实习文字字符串便宜且简单,因此默认情况下完成。实际动态分配的字符串通常以大量时间为代价节省少量字节,因此不值得为而烦恼。如果你想强迫实习,你可以自己动手。

答案 2 :(得分:1)

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

myString3myString4是引用相等的,因为编译器interns the strings:在编译时用字符串文字初始化的字符串值最终是在运行时引用同一个对象:

  

公共语言运行库通过维护a来保存字符串存储   表,称为实习池,包含单个引用   以编程方式声明或创建的每个唯一文字字符串   你的计划。因此,带有一个文字字符串的实例   特殊值仅在系统中存在一次。

     

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

答案 3 :(得分:0)

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

答案 4 :(得分:0)

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

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

我看到的方式是,对于myString和myString2,你使用char []创建了那些,并且在创建字符串时,Intern池中没有默认查找。

对于myString3和myString4, myString3为InternPool和myString4增加了值,你只需要一个引用,因为它是样本块。

我之前的印象是,早期版本的框架IsIntern是可选的,让开发人员。看起来不一定是这种情况