当存在指定类型的运算符重载时,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# 中是不可变的 - 当您将字符串添加在一起时,会生成一个新的字符串实例 - 这在第二个代码集中永远不会发生,因此它们实际上都引用 RAM 中的相同字节块。