由MSDN提供的等于覆盖的奇怪转换

时间:2015-09-26 10:56:41

标签: c# casting

我正在查看来自MSDN Guidelines for Overloading Equals() and Operator ==

的文章

我看到以下代码

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 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;
    }
}

这又一次只能检查if(p == null)

3 个答案:

答案 0 :(得分:7)

(object)p == null使用内置的==运算符,在这种情况下检查引用相等性。 p == null会为指定的类型调用重载的operator==。如果重载operator==将以Equals(在您链接到的示例中未实现)实现,那么您将获得无限递归。即使它没有以Equals的形式实现,它仍然会做更多的工作。

答案 1 :(得分:4)

只是为了完成这两个答案,您查看的文档已经过时,如页面顶部所述。如果你看一下newer guidelines,就会有一个说明正确解释原因的原因:

  

operator ==的重载中的常见错误是使用(a == b),(a ==   null)或(b == null)检查引用相等性。 相反   创建对重载运算符的调用==,导致无限   循环。使用ReferenceEquals或将类型转换为Object,以避免使用   循环。

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

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

答案 2 :(得分:2)

这是为了确保被调用的==运算符是Object的默认实现,而不是用户定义的实现。通过让自己的运算符自己调用,在这样的代码中引入无界递归是一个常见的错误。