C# MSDN代码示例:为什么它在调用base.Equals(对象)之前强制转换?
在Microsoft的MSDN库关于C# MSDN代码示例:为什么它在调用base.Equals(对象)之前强制转换?,c#,equals,equality,C#,Equals,Equality,在Microsoft的MSDN库关于Object.EqualsMethod(Object)()的文章中,给出了一个示例来演示如何重写Equals。看起来是这样的: class Point { ... // IEquatable<Point> is not implemented. public override bool Equals(Object obj) { //Check for null and compare run-time types.
Object.Equals
Method(Object)()的文章中,给出了一个示例来演示如何重写Equals。看起来是这样的:
class Point
{
... // IEquatable<Point> is not implemented.
public override bool Equals(Object obj)
{
//Check for null and compare run-time types.
if ((obj == null) || ! this.GetType().Equals(obj.GetType())) {
return false;
}
else {
Point p = (Point) obj;
return (x == p.x) && (y == p.y);
}
}
}
sealed class Point3D: Point
{
int z;
public override bool Equals(Object obj)
{
Point3D pt3 = obj as Point3D;
if (pt3 == null)
return false;
else
return base.Equals((Point)obj) && z == pt3.z; // Here!!!
}
}
将
obj
转换为点
没有意义(哈哈)。您是对的,Point.Equals
方法也会将其强制转换为点
。它是多余的。在Point类中,我们正在比较以下类型:
this.GetType().Equals(obj.GetType())
类型点不等于点3D。当需要进行相等性检查时,今天的建议是实现通用接口。它的方法提供了类型安全性,并避免了值类型的装箱/拆箱开销 如果
Point
类实现了IEquatable
接口,那么它将包含Equals(Point)
方法重载,这比Equals(Object)
调用效率更高。一个合理的理由可能是,在所述接口实现的情况下,对点
的类型转换是先发制人的
class Point : IEquatable<Point>
{
public Equals(Point other)
{
return other != null && this.x == other.x && this.y == other.y;
}
public override bool Equals(Object obj)
{
return this.Equals(obj as Point);
}
}
类点:i可满足
{
公共平等(其他点)
{
返回other!=null&&this.x==other.x&&this.y==other.y;
}
公共覆盖布尔等于(对象对象对象)
{
返回此.Equals(obj作为点);
}
}
在我看来不是好代码。强制转换意味着,如果obj
属于外来类型,他们将获得InvalidCastException
。不太好。编辑:不,对不起,太快了。他们知道类型是Point3D
,所以没有例外,只是看起来很傻的代码。也许它应该传入pt3
,它已经被铸造了,而不是obj
。编辑:或者至少传入obj
,让基本实现处理强制转换/类型检查。我认为他们正在尝试使基类方法工作,尽管!这个.GetType().Equals()
检查。(毫无意义地尝试。正确的方法可能是使用IEquatable
,而不是重写Object.Equals()
,以便在类层次结构中进行比较。)或者,显然,避免数据结构的疯狂层次结构Point3D
从Point
扩展以保存两个字段定义似乎是对继承的错误使用。@但是,当比较两个Point3D
时,它仍然有效。在基类中,GetType()
和obj.GetType()
都将返回typeof(Point3D)
,因此一切正常。但它是丑陋的代码。在我看来,基类上的Equals函数没有很好的定义cast(Point)obj
不会更改被引用对象的标识。这只是一个引用转换(在本例中是无用的)。无论编译时类型是什么,GetType()
都将始终返回真正的运行时类型。当为非密封类类型重写Equals
时,检查GetType()
和obj.GetType()
是否相同是一件非常好的事情。您仍然应该在类型安全重载(接口实现)中检查GetType()==other.GetType()
当您的类
未密封时@杰佩斯蒂格尼尔森:这是有争议的。如果派生类实例的基类字段等于当前基类实例,则这两个字段可能仍然被视为相等。1<代码>点不是值类型。2.不建议在可能有争议的非密封类上实施IEquatable
。但是你破坏了等于关系的对称性。也就是说,如果我从您的类型派生(您没有密封它)并引入新的z
组件,那么jeppes3DPointInstance.Equals(douglasPointInstance)
肯定会返回false
。但是我无法让您的类型在douglasPointInstance.Equals(jeppes3DPointInstance)
中“正确”运行。可继承类型通常不应该实现IEquatable
,因为没有好的模式来确保调用IEquatable.Equals(BaseType)派生类型对象上的
将产生与其对
对象的重写一致的行为。Equals(object)
,除非将前一个方法链连接到后一个方法(这将首先否定实现接口的所有性能好处)。
class Point : IEquatable<Point>
{
public Equals(Point other)
{
return other != null && this.x == other.x && this.y == other.y;
}
public override bool Equals(Object obj)
{
return this.Equals(obj as Point);
}
}