鉴于这两个陈述...
((object)false) == ((object)false)
((object)false).Equals((object)false)
第一条语句返回 false。第二个语句返回 true。
我明白为什么第一个语句返回 false - 当布尔值被装箱时,它变成了引用类型,并且两个引用不相等。但是,为什么/如何第二个陈述结果为真?
因为它Equals
基本上仍在调用多态方法。
使用不同类型演示的示例代码:
using System;
struct Foo
{
public override bool Equals(object other)
{
Console.WriteLine("Foo.Equals called!");
return true;
}
public override int GetHashCode()
{
return 1;
}
}
class Program
{
static void Main(string[] args)
{
object first = new Foo();
object second = new Foo();
first.Equals(second);
}
}
那仍然打印“Foo.Equals call!” 因为在“盒子”上调用 Equals 方法仍然调用Foo.Equals
.
现在==
没有被覆盖,它被重载......所以如果你写:
object first = ...;
object second = ...;
bool same = first == second;
这将始终比较参考身份,而无需运行任何特定于类型的代码。
这篇文章或许能回答你的问题:
正如您所说,第一个示例检查引用是否相等,而第二个示例检查每个对象的相等值。
来自MSDN:
对于 Equals 方法的所有实现,以下语句必须为真。在列表中,x、y 和 z 表示不为空的对象引用。
x.Equals(x) 返回 true,但涉及浮点类型的情况除外。参见 IEC 60559:1989,微处理器系统的二进制浮点运算。
x.Equals(y) 返回与 y.Equals(x) 相同的值。
如果 x 和 y 都是 NaN,则 x.Equals(y) 返回 true。
如果 (x.Equals(y) && y.Equals(z)) 返回 true,则 x.Equals(z) 返回 true。
只要 x 和 y 引用的对象没有被修改,对 x.Equals(y) 的连续调用就会返回相同的值。
x.Equals(null) 返回 false。
运算符重载不是多态的,而是多态Equals
的。即使bool
有一个重载的 ==,通过将其转换为object
您正在使用object
的实现,它比较引用相等性。但是您仍在bool
使用Equals
.
该Equals
方法是一个被Boolean
类型覆盖的虚方法。因此,在第二行中将其转换bool
为 an并不重要;object
它仍然使用类型的 vtable 来查找Equals
对象的实际类型提供的实现(这对你来说是多态性!)。
该==
运算符是一个静态运算符,因此在编译时选择了适当的重载。编译器看到您object
使用该运算符比较两个类型的对象,因此它选择(object, object)
重载。
这是一个愚蠢的小程序来说明差异:
class Thing
{
public virtual void AnnounceSelf()
{
Console.WriteLine("I am a Thing.");
}
public static void AnnounceThing(Thing other)
{
Console.WriteLine("Here is a Thing.");
}
public static void AnnounceThing(OtherThing other)
{
Console.WriteLine("Here is ANOTHER type of Thing.");
}
}
class OtherThing : Thing
{
public override void AnnounceSelf()
{
Console.WriteLine("I am ANOTHER Thing.");
}
}
class Program
{
public static void Main()
{
Thing t = new Thing();
// Outputs "I am a Thing." as expected.
t.AnnounceSelf();
// Outputs "Here is a Thing." as expected.
Thing.AnnounceThing(t);
t = new OtherThing();
// This method is virtual, so even though t is typed as Thing,
// the implementation provided by OtherThing will be called;
// outputs "I am ANOTHER Thing."
t.AnnounceSelf();
// In contrast to above, this method will NOT call the more
// specific overload of AnnounceThing (accepting an OtherThing
// argument) because t is only typed as Thing, so the compiler
// will go with the first;
// outputs "Here is a Thing."
Thing.AnnounceThing(t);
// THIS will output "Here is ANOTHER type of Thing."
Thing.AnnounceThing((OtherThing)t);
}
}
第一个是参考,第二个是价值!