字符串不变性 C#(堆内存,新运算符)

String immutability C# (Heap memory, new operator)

最近学习了Stack和Heap,想请教一下。我一直在“试验”字符串,但我无法解释 - 如果我在堆上创建两个不同的内存块,为什么以下内容为真?

        static void Main()
    {
        string test = "yes";
        string secondTest = "yes";
        Console.WriteLine(test == secondTest); //true
        string thirdTest = new string("yes");
        Console.WriteLine(secondTest == thirdTest); //true
    }

第一个字符串testsecondTest是一样的,因为它们有相同的参考值,但是我创建第三个字符串thirdTest的时候我不是在创建一个新的吗使用“new”在堆上分配内存块?

为什么还是这样?

我的猜测:

我写的完全一样,我误解了new运算符,因为我看教程时,它们是Java语言

String name = "John" 
String aThirdName = new String("John")
System.out.printIn(name == aThirdName); // false

这意味着我想的不一样

(string test = "yes") = (string thirdTest = new string("yes"))

其实是一样的。 (我的意思是这两行是类比的)

如果我的猜测是正确的,如何在堆上创建一个具有相同值的新内存块? (我想知道,只是为了学习,我知道内存有很多相同值的变量在堆内部的不同内存块上是无效的)

如评论中所述,string 是一个不好的例子,因为它覆盖了 == 运算符和覆盖了 equals 方法。对于字符串,它是一个引用类型,但由于许多覆盖和其他行为,它实际上(在大多数情况下)表现得像一个值类型(尤其是在相等性方面)。

也就是说,如果您要创建一个简单的 class,您会发现您的测试完全符合您的预期。


String 中覆盖相等性的片段,为您提供一些背景信息。

public static bool operator ==(string? a, string? b)
{
    return string.Equals(a, b);
}
// Determines whether two Strings match.
public static bool Equals(string? a, string? b)
{
    if (object.ReferenceEquals(a,b))
    {
        return true;
    }

    if (a is null || b is null || a.Length != b.Length)
    {
        return false;
    }

    return EqualsHelper(a, b);
}

然后它开始进入一个EqualsHelper代码的兔子洞,这里不值得追逐(如果你有兴趣,你可以反编译它或在网上找到它)。

string firstTest=new string("test")string secondTest="test" 是一样的,第二个版本只是语法糖。关于为什么firstTest==secondTest //true,这就是为什么class 字符串覆盖方法Equals和运算符(==)也被覆盖并使用Equals