使用“==”运算符和Equals方法在装箱布尔类型上有什么区别?

6

考虑以下两个陈述...

((object)false) == ((object)false)
((object)false).Equals((object)false)

第一条语句返回false。 第二条语句返回true。
我理解为什么第一条语句返回false——当布尔值被装箱时,它变成了引用类型,而这两个引用不相等。但是,第二条语句如何得到true的结果呢?
6个回答

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 called!",因为在“box”上调用Equals方法仍会调用Foo.Equals。

现在,==没有被重写,而是被重载了......所以如果你写:

object first = ...;
object second = ...;
bool same = first == second;

这将始终进行引用标识的比较,而不会运行任何类型特定的代码。


5

1

Equals方法是一个虚方法,被Boolean类型重写。所以在第二行中将bool转换为object并不重要;它仍然使用类型的虚函数表来查找由对象的实际类型提供的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);
    }
}

1

正如你所说,第一个示例检查引用是否相等,而第二个示例检查每个对象的相等值。

来自MSDN

Equals方法的所有实现都必须满足以下语句。在列表中,x、y和z表示不为null的对象引用。

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。


1

运算符重载不是多态的,但Equals是。即使bool有一个重载的==,通过将其转换为object,您正在使用object的实现,它比较引用相等性。但您仍然在使用bool版本的Equals


-1

第一个是用于引用,第二个是用于值!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接