C# MSDN提供的奇怪强制转换等于覆盖

C# MSDN提供的奇怪强制转换等于覆盖,c#,casting,C#,Casting,我正在看MSDN的文章 我看到了下面的代码 public override bool Equals(object obj) { // If parameter is null return false. if (obj == null) { return false; } // If parameter cannot be cast to Point return false. TwoDPoint p = obj as TwoDP

我正在看MSDN的文章

我看到了下面的代码

public override bool Equals(object obj)
{
    // If parameter is null return false.
    if (obj == null)
    {
        return false;
    }

    // If parameter cannot be cast to Point return false.
    TwoDPoint p = obj as TwoDPoint;
    if ((System.Object)p == null)
    {
        return false;
    }

    // Return true if the fields match:
    return (x == p.x) && (y == p.y);
}
奇怪的是第二个if中的cast to对象

// If parameter cannot be cast to Point return false.
TwoDPoint p = obj as TwoDPoint;
if ((object)p == null)
{
    return false;
}
为什么p被再次铸造为对象?写这个还不够吗

// If parameter cannot be cast to Point return false.
TwoDPoint p = obj as TwoDPoint;
if (p == null)
{
    return false;
}
如果p不能强制转换为TwoDPoint,那么它的值将为null。我很困惑,也许我不明白一些琐碎的事情

编辑

在另一个Equals方法中提供了另一个此类强制转换

public bool Equals(TwoDPoint p)
{
    // If parameter is null return false:
    if ((object)p == null)
    {
        return false;
    }
}

在这里,如果(p==null)
(对象)p==null
使用内置的
=
操作符,则只需检查
就足够了,在这种情况下,该操作符检查引用相等性
p==null
将为指定类型调用重载的
运算符==
。如果重载的
操作符==
将按照
等于
的方式实现(在您链接到的示例中不是这样),那么您将拥有无限递归。即使它没有按照
Equals
的方式实现,它仍然会做比需要做的更多的事情。

这是为了确保调用的==运算符是来自对象的默认实现,而不是用户定义的实现。在这样的代码中引入无界递归是一个常见的错误,让您自己的操作符调用它们自己。

为了完成这两个答案,您查看的文档已经过时,如页面顶部所述。如果您查看,会看到一个注释,它确切地解释了为什么要这样做:

运算符==重载中的一个常见错误是使用(A==b),(A== null),或(b==null)来检查引用是否相等而是这个 创建对重载运算符==的调用,从而导致 循环。使用ReferenceEquals或将类型强制转换为对象,以避免 循环

基本上,这样做等同于使用,这就是代码实际要做的:

TwoDPoint p = obj as TwoDPoint;
if (object.ReferenceEquals(p, null))
{
    return false;
}

这是一种代码气味。他们应该使用ReferenceEquals。