尽管 String 是引用类型,为什么“==”运算符在 2 个字符串中表现正确?

Moh*_*mad 1 .net c#

我们知道 String 是一种引用类型并且是不可变的,所以这样做是合理的。它表示存储在 Stack 中的字符串的地址及其在 Heap 部分内存中的内容存储。另一方面,我们知道“==”操作只是比较堆栈值。因此,例如,我们有以下代码,如我们在理论上所期望的那样比较两个对象。

在 Microsoft Docs 中,我们有:

默认情况下,如果两个非记录引用类型操作数引用同一个对象,则它们是相等的:

   public static void Main()
    {
        var a = new MyClass(1);
        var b = new MyClass(1);
        var c = a;
        Console.WriteLine(a == b);  // output: False
        Console.WriteLine(a == c);  // output: True
    }
Run Code Online (Sandbox Code Playgroud)

但我的问题是为什么在引用类型为“==”的字符串中,操作的行为类似于值类型!我只是对技术原因以及 Dotnet 如何为之而感到好奇,而不仅仅是概念(如这里

string t1 = "test";
string t2 = "test";
bool result = t1 == t2; // output: True
Run Code Online (Sandbox Code Playgroud)

Evk*_*Evk 7

如评论中所述,stringtype 仅实现自定义相等比较运算符。任何类都可以这样做并使==(和其他相等运算符)表现得“像值类型”。例如,这就是对新的“记录”类型所做的,这些类型是引用类型但行为“类似”值类型。

然而,还有一件事。在您的示例代码中:

string t1 = "test";
string t2 = "test";
bool result = t1 == t2; // output: True
Run Code Online (Sandbox Code Playgroud)

即使您检查两个字符串是否实际引用同一个对象,它仍然会返回 true:

bool result = Object.ReferenceEquals(t1, t2); // output: True
Run Code Online (Sandbox Code Playgroud)

那是因为它们实际上是指同一个对象,因为字符串实习。程序中有一个全局字符串池,可以在其中放置一个字符串,或者如果字符串已经存在 - 获取对同一字符串的引用(通过String.Intern调用)。程序中自动声明的所有字符串文字都放在那里。这意味着双方t1t2指向同一个字符串对象在池中实习生。

如果您执行以下操作:

string t1 = "test";
string t2 = new StringBuilder().Append("test").ToString();
bool result = Object.ReferenceEquals(t1, t2);
Run Code Online (Sandbox Code Playgroud)

然后t2不再自动实习并且比较将返回假(但当然,比较==仍然会返回真)。