C#中的Object.Equals澄清?

时间:2013-02-16 21:33:28

标签: c# .net equals

我做了一个简单的测试:

     object t = 3;
     object aa = 3;
#1   Console.WriteLine(t.Equals(aa));  
#2   Console.WriteLine(t.Equals(3));  
#3   Console.WriteLine(3.Equals(aa));  

所有这些都是真的。(这实际上是我的问题)。

查看object,这是使用过的函数:

 public virtual bool Equals(object obj);

等于是虚拟的。所以它可以被覆盖。

但我看到任何多态行为。这只是一个纯粹的盒装价值。

  • 关于第1行t.Equals(aa)

    引用类型是静态类型 - 对象。

    所以我认为它应该调用Object.Equals:这意味着引用不同,这意味着第一个答案应该是False。(我可能在这里错了)。这是为什么?

  • 关于第2行t.Equals(3)

    同样,t's静态类型是对象。所以Object.Equals正在运行。怎么会true

  • 关于第3行3.Equals(aa)

    我认为public override bool Equals(object obj);正在运行,因为静态类型为in t。而param类型是对象。但为什么会true?它取消了价值吗?

似乎有些东西在某种程度上取消了对象而没有我注意到: - (

3 个答案:

答案 0 :(得分:8)

Object s Equals方法具有多态性,因此可以通过int等子类型覆盖。 Int32.Equals重写此方法以在当前对象及其参数之间进行值比较,并且由于参数在取消装箱后相等,因此返回true。

Int32.Equals - bool Equals(object)bool Equals(int)有两个重载。 bool Equals(object)重载是object覆盖的重载。由于taaobject引用,因此这是在示例1和2中调用的方法。

在示例3中,由于aaobject,因此仍然会调用此重载,因此这是唯一有效的重载。

==运算符是静态的,并根据其参数的类型进行静态解析,这些参数在您的示例中均为object==的{​​{1}}运算符会比较引用,在这种情况下,将为两个单独的盒装整数返回false。

答案 1 :(得分:5)

正在调用虚方法Object.Equals,但由于虚方法的工作方式,它会调用Int32.Equals方法,而是比较int值,而不是引用。< / p>

虚拟方法在运行时绑定。也就是说,它们在运行时选择适当的方法,而不是在编译时。在这种情况下,Object.Equals是编译代码中的内容,但由于您要比较int s,它会在运行时选择Int32.Equals。这是通过使用称为v-tables的东西来完成的(如果你想阅读更多内容)。

请记住Equals应该这样做,如果你真的想要引用相等,你可以使用ReferenceEquals

请注意,这与拳击没有任何关系。您将获得相同的行为,例如,string或自定义类。

答案 2 :(得分:0)

正如您在问题中所写,以下断言将全部通过

[Test] 
public void EqualityOnInts()
{
    object a = 1;
    object b = 1;

    Assert.AreEqual(a, b);
    Assert.IsTrue(1.Equals(a));
    Assert.IsTrue(b.Equals(1));
}

如果您实例化a,则会创建一个值为1的新integer对象。在Equals上调用a方法将导致调用Equals方法在Int32。另外,如果你做a.GetType() it will return Int32`。

由于Equals的{​​{1}}实现将检查值是否相等,并且不关心不同的对象引用,结果将为“true”。