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

本文关键字:泛型方法 何确定 引用 编译器 存在 类型 运算符 重载 | 更新日期: 2023-09-27 18:36:36

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

存储在类中的公共函数;请注意,"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 的解释一致,当我运行时驱动程序文件的输出是"真"、"假"。 现在,我以为我完全理解了这一点,但是当我将驱动程序文件更改为以下内容时,我感到惊讶:

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

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

感谢您抽出宝贵时间阅读和回复。

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

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