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

时间:2011-03-01 17:57:40

标签: c# boxing

鉴于这两个陈述......

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

第一个语句返回false。 第二个语句返回true。

我理解为什么第一个语句返回false - 当布尔值被装箱时,它变成一个引用类型,并且两个引用不相等。但是,为什么/第二个陈述如何导致真实?

6 个答案:

答案 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)

第一个用于参考,第二个用于值!