为什么Object类型的Equals的输入参数?

时间:2015-01-26 07:54:42

标签: c# equals

我已经覆盖了 Equals(对象输入)数千次,并且从未考虑过这个问题。现在,经过几次喝酒后,我开始思考它,它让我感到震惊,我不能完全确定为什么会这样。

平等操作在语义上是检查两个东西是否是自身的副本。通常,它是基于指针(参考值或任何人可能想要调用它)完成的。有时,我们希望将平等定义为例如实例 a 的某些属性的总和与实例 b 的属性相同,不一定在任何属性上相等。

但是,不同类型的两个对象不能具有相同的引用,可以吗?并且,即使两种类型具有相同的属性集(称为相同的,键入相同的属性),它仍然是苹果和橙子,因此比较将无意义(至少)或损坏逻辑。

是否有任何(我的意思是任何 Equals 操作的输入可能属于不同类型的情况,然后是仍然是有意义吗?

1 个答案:

答案 0 :(得分:7)

你的假设是错误的:

  

平等操作在语义上是检查两个东西是否是自身的副本。通常,它是基于指针(参考值或任何人可能想要调用它)完成的。

那是引用相等,它由函数Object.ReferenceEquals检查(它是静态的,不可覆盖的)

对象相等性不同,您可以应用所需的规则。如果它不是那样的话,你会如何检查两个值类型(它们在C#中不能保存相同的引用)?

考虑:

int a = 5;
int b = 5;
a.Equals(b); // what would this return? `a` and `b` are different objects

现在,对于问题的第二部分,根据您的需要,可能需要将对象视为不同类型的对象。考虑:

public class Point2D {
  public int X, Y;
}

public class Point3D {
  public int X, Y, Z;

  public override bool Equals(object source) {
    var p2D = source as Point2D;
    if(p2D != null)
    {
      if(this.Z == 0 && p2D.X == this.X && p2D.Y == this.Y)
        return true;
      return false;
    }
    //...
  }
}

在这种情况下:

var p2D = new Point2D(5,5);  // <-- let's pretend we have the right constructor  
var p3D = new Point3D(5,5,0);
object.Equals(p3D,p2D); // <-- returns true
object.ReferenceEquals(p3D, p2D); // <-- returns false

对于性能(特别是对于值类型),您可能希望实现IEquatable<T>IEqualityComparer<T>(或者更好,来自EqualityComparer<T>),这允许直接比较特定类型(无需在之前将其包装到object),但这超出了本答案的范围。

请注意,如果您实现此接口,仍然建议覆盖Object.Equals,以便在两者之间匹配行为。