鉴于这两个陈述......
((object)false) == ((object)false)
((object)false).Equals((object)false)
第一个语句返回false。 第二个语句返回true。
我理解为什么第一个语句返回false - 当布尔值被装箱时,它变成一个引用类型,并且两个引用不相等。但是,为什么/第二个陈述如何导致真实?
答案 0 :(得分:8)
因为它仍在调用多态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!”因为在“框”上调用Equals方法仍然会调用Foo.Equals
。
现在==
未被覆盖,它是重载 ...所以如果你写:
object first = ...;
object second = ...;
bool same = first == second;
这将始终比较参考标识,而永远运行任何类型特定的代码。
答案 1 :(得分:5)
本文或许可以回答您的问题:
答案 2 :(得分:1)
正如您所说,第一个示例检查引用是否相等,而第二个示例检查每个对象的值是否相等。
来自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。
答案 3 :(得分:1)
运算符重载不是多态的,但Equals
是。即使bool
有一个重载的==,通过将其转换为object
,您正在使用object
的实现,它会比较引用相等性。但您仍在使用bool
的{{1}}版本。
答案 4 :(得分:1)
Equals
方法是一种被Boolean
类型覆盖的虚方法。因此,在第二行中将bool
转换为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);
}
}
答案 5 :(得分:-1)
第一个用于参考,第二个用于值!