当指定类型的运算符重载存在时,C# 编译器如何确定泛型方法中的引用相等性?

How does C# compiler determine reference equality in generic methods when operator overloads for a specified type exists?

目前正在阅读 Jon Skeet 的 "C# In Depth, 3rd edition",我有一个关于引用相等性的小问题。对于那些感兴趣的人,以下代码是第 3 章第 80 页 Jon 代码的一个小变体:

Public函数存储在一个class中;请注意 'T' 仅限于引用类型:

    public static bool AreReferencesEqual<T>(T i1, T i2) where T : class
    {
        return i1 == i2;
    }

驱动方式:

    static void Main(string[] args)
    {
        string name = "Joe";
        string one = "one" + name;
        string two = "one" + name;
        // test one (uses string operator== overload, and returns true)
        Console.WriteLine(one == two);

        // test two (according to Jon, when the compiler compiles the generic method,
        // it has no idea what overloads will be provided, and therefore treats
        // the == comparison with respect to the more general 'object' type.
        // Therefore this method should return false because, of course, the value
        // of the references 'one' and 'two' are not the same.
        Console.WriteLine(ReferenceEquality.AreReferencesEqual(one, two));
    }

与Jon的解释一致,我运行时驱动文件的输出是"True","False"。现在,我以为我完全理解了这一点,但是当我将驱动程序文件更改为这样时,我感到很惊讶:

    static void Main(string[] args)
    {
        string one = "one";
        string two = "one";
        Console.WriteLine(one == two);
        Console.WriteLine(ReferenceEquality.AreReferencesEqual(one, two));
    }

并在输出中看到 "True"、"True"。这背后的原因是什么?泛型方法现在是否使用字符串运算符== 重载,或者由于我不知道的一些微妙的编译器技术,引用确实相等?还是我完全误会了并误解了乔恩的解释?

感谢您花时间阅读和回复。

它们是引用等效的,因为编译器使用相同的底层字符串,因为常量匹配。字符串(在幕后)在 C# 中是不可变的 - 当您将字符串加在一起时,会生成一个新的字符串实例 - 这在您的第二个代码集中永远不会发生,因此它们实际上都引用 RAM 中的相同字节块。