2010-02-09 57 views
16

一)由于字符串是不可变的,所以具有相同字符串值的变量指向同一个字符串对象吗?

 string s = "value"; 
     string s1 = "value"; 

待办事项S和S1引用变量指向同一个字符串对象(我假设这是由于这样的事实:string是不可改变的)? b)我意识到等式运算符(==,>等)已被重新定义以比较字符串对象的值,但在使用静态方法比较两个字符串时是相同的。Object.Equals()和Object.ReferenceEquals( )?

感谢名单

+2

我不是专家,但检查此链接上的字符串internment。 http://en.csharp-online.net/CSharp_String_Theory%E2%80%94String_intern_pool – ChaosPandion 2010-02-09 19:27:00

+10

另请参阅我对此的文章,了解其他一些注释:http://blogs.msdn.com/ericlippert/archive/2009/09/ 28/string-interning-and-string-empty.aspx – 2010-02-09 19:35:25

+0

@Eric - 非常棒的阅读,感谢您发布该链接。 – ChaosPandion 2010-02-09 19:41:24

回答

21

不,不是所有具有相同值的字符串都是相同的对象引用。

由编译器生成的字符串将全部为Interned并成为相同的引用。在运行时生成的字符串默认情况下不会被执行,并且会是不同的引用。

var s1 = "abc"; 
var s2 = "abc"; 
var s3 = String.Join("", new[] {"a", "b", "c"}); 
var s4 = string.Intern(s3); 
Console.WriteLine(ReferenceEquals(s1, s2)); // Returns True 
Console.WriteLine(ReferenceEquals(s1, s3)); // Returns False 
Console.WriteLine(s1 == s3); // Returns True 
Console.WriteLine(ReferenceEquals(s1, s4)); // Returns True 

注意上面,你可以强制使用String.Intern(string),然后允许您使用对象的平等,而不是字符串平等一些检查,这是更快的被拘留串线。这是非常常用的一个例子是在生成的XML序列化程序代码和名称表中。

+1

+1用于说明在运行时创建的字符串必须手动执行。 – ChaosPandion 2010-02-09 19:34:09

+0

可能值得添加 var s4 = string.Intern(s3); Console.WriteLine(ReferenceEquals(s1,s4)); //返回True – Dolphin 2010-02-09 19:38:41

+0

@Dolphin,好点,我更新了答案。 – 2010-02-09 19:41:18

3

是的,这些将指向相同的字符串,因为他们都定义为字符串文字。如果以编程方式创建字符串,则必须手动插入字符串。

这是因为.NET框架将程序中的字符串文字实例化为实习池。您可以使用String.Intern来检索此引用,或者手动实习您自己的运行时生成的字符串。

详情,请参阅docs for Intern

因此,文字串与特定值的一个实例只存在于系统中一次。

例如,如果分配相同的文字串,以多个变量时,运行时检索相同的参考从实习生池文字串并将其分配给各可变

+2

但是,这是通过实施,而不是规范。 – 2010-02-09 19:33:14

+0

正确 - 但实现确实可以做到这一点,目前,字面值。 – 2010-02-09 19:35:38

+0

我在回答中加了一些说明。 – 2010-02-09 19:37:04

2

随着当前CLR相同字面字符串指向相同的实际对象。这个过程被称为实际并适用于所有编译时间字符串。

在运行时创建的字符串不是默认实现的,但可以通过调用string.Intern将其添加到实参集合中。

有关如何存储.NET字符串的详细说明,请参阅my answer for this question

相关问题