Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/339.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# MSDN代码示例:为什么它在调用base.Equals(对象)之前强制转换?_C#_Equals_Equality - Fatal编程技术网

C# MSDN代码示例:为什么它在调用base.Equals(对象)之前强制转换?

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.

在Microsoft的MSDN库关于
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);
   }
}