为什么Equals的入参是Object类型的?
Why is the input parameter of Equals of type Object?
我已经重写了 Equals(Object input) 数千次,但从未更深入地考虑过这个问题。现在,喝了几杯之后,我开始思考它,我不完全确定为什么会这样。
从语义上讲,相等操作是检查两个事物是否是其自身的副本。通常,它是基于指针(参考值或任何可能想要调用它的东西)完成的。有时,我们想将等式定义为例如实例 a 的某些属性的总和与实例 b 的某些属性的总和相同,但不一定在其中任何一个上都相等。
但是,不同类型的两个对象不能有相同的引用,对吗?而且,即使两个类型具有相同的属性集,名称相同,类型相同,它仍然是苹果和橘子,所以比较要么毫无意义(至少)要么对逻辑造成严重破坏。
有没有(我的意思是任何)Equals操作的输入可能是不同类型的情况那么比较者 仍然 有意义吗?
你的假设是错误的:
Equality operation is semantically speaking checking if two thingies are a copy of itself. Generally, it's done based on the pointer (reference value or whatever one might want to call it).
那是引用相等性,它由函数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
,以便两者之间的行为匹配。
我已经重写了 Equals(Object input) 数千次,但从未更深入地考虑过这个问题。现在,喝了几杯之后,我开始思考它,我不完全确定为什么会这样。
从语义上讲,相等操作是检查两个事物是否是其自身的副本。通常,它是基于指针(参考值或任何可能想要调用它的东西)完成的。有时,我们想将等式定义为例如实例 a 的某些属性的总和与实例 b 的某些属性的总和相同,但不一定在其中任何一个上都相等。
但是,不同类型的两个对象不能有相同的引用,对吗?而且,即使两个类型具有相同的属性集,名称相同,类型相同,它仍然是苹果和橘子,所以比较要么毫无意义(至少)要么对逻辑造成严重破坏。
有没有(我的意思是任何)Equals操作的输入可能是不同类型的情况那么比较者 仍然 有意义吗?
你的假设是错误的:
Equality operation is semantically speaking checking if two thingies are a copy of itself. Generally, it's done based on the pointer (reference value or whatever one might want to call it).
那是引用相等性,它由函数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
,以便两者之间的行为匹配。