奇怪的字符串文字比较

时间:2011-11-29 20:09:08

标签: c# string

深入了解C#,我遇到了一个与对象引用相等的小问题。 我说我有两个字符串:

String a = "Hello world!";
String b = "Bonjour le monde";
bool equals = ReferenceEquals(a, b);  // ******************* (1)
b = "Hello world!";
equals = ReferenceEquals(a, b);       // ******************* (2)

(1) false是预期的。 ReferenceEquals Documentation

  

ReferenceEquals比较实例

然后:

  • 为什么(2)会返回true
  • 字符串ab不是同一个对象吗?如果是,那么它们是如何变得相同的,因为我从未明确地a=b

4 个答案:

答案 0 :(得分:24)

这是因为string interning

  

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

     

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

答案 1 :(得分:9)

.NET运行时自动为interned字符串文字。这意味着对具有相同值的字符串文字共享相同的字符串实例。这样做是为了减少内存使用并提高性能。这是一个安全的优化,因为字符串是不可变的。

您的代码会编译为CIL指令,类似于以下内容:

IL_0001: ldstr "Hello world!"
IL_0006: stloc.0
IL_0007: ldstr "Bonjour le monde"
IL_000c: stloc.1
etc...

ECMA specification中的ldstr(“加载文字字符串”)说明文档:

  

默认情况下,CLI保证两个ldstr指令的结果引用两个元数据标记   具有相同的字符序列,返回完全相同的字符串对象(称为“字符串”的过程   interning“)。可以使用System.Runtime.CompilerServices.CompilationRelaxationsAttributeSystem.Runtime.CompilerServices.CompilationRelaxations.NoStringInterning来控制此行为。

您也可以通过调用方法String.Intern来实习自己。

答案 2 :(得分:4)

字符串文字大多数时候都是同一个对象,因为它们是常量和不可变的。

取自microsoft docs

  

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

产生的输出
class Test
{
   static void Main() {
      object a = "hello";
      object b = "hello";
      System.Console.WriteLine(a == b);
   }
}
  

为True,因为两个文字引用相同的字符串实例。

答案 3 :(得分:3)

.NET维护一个字符串池,因为它们是不可变的。你不必关心它,因为它自己需要重用它们。