奇怪的字符串文字比较

GET*_*Tah 16 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)
Run Code Online (Sandbox Code Playgroud)

(1)false和那是预期的.ReferenceEquals 文档

ReferenceEquals比较实例

但是之后:

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

wsa*_*lle 24

这是因为字符串实习.

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

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


Mar*_*ers 9

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

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

IL_0001: ldstr "Hello world!"
IL_0006: stloc.0
IL_0007: ldstr "Bonjour le monde"
IL_000c: stloc.1
etc...
Run Code Online (Sandbox Code Playgroud)

ECMA规范中的ldstr("加载文字字符串")指令的文档:

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

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


MBy*_*ByD 5

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

摘自微软文档

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

class Test
{
   static void Main() {
      object a = "hello";
      object b = "hello";
      System.Console.WriteLine(a == b);
   }
}
Run Code Online (Sandbox Code Playgroud)

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