Cast to object before null check in overriding Equ

2019-02-12 16:39发布

Just reading the msdn article on overriding equality operators here

The following snippet confuses me...

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

Why is there a cast to Object here to perform the null comparison?

6条回答
Rolldiameter
2楼-- · 2019-02-12 17:43

No! if you don't do that, the runtime will start a recursive call to the equality operator you are just in which results in infinite recursion and, consequently, a stack overflow.

查看更多
一夜七次
3楼-- · 2019-02-12 17:43

the below is the line that does the cast

TwoDPoint p = obj as TwoDPoint

the difference with the "normal" cast is that using "As" it doesn't raise an exception if the object is not "castable". In this case if "p" is not a TwoDPoint Type is not gonna raise an exception (cast not valid) but return null.

if ((System.Object)p == null) // <-- wtf? 
{ 
    return false; 
} 

this code check if the cast went fine if not p should be null for the reason above

查看更多
Melony?
4楼-- · 2019-02-12 17:44

This is not useless. Without that cast the == operator being overloaded would be called recursively...

查看更多
我命由我不由天
5楼-- · 2019-02-12 17:45

To force it to use the Equals method of Object rather than its own overloaded version... just a guess...

查看更多
别忘想泡老子
6楼-- · 2019-02-12 17:46

Operators apply through static analysis (and overloads), not virtual methods (overrides). With the cast, it is doing a reference equality check. Without the cast, it can run the TwoDPoint operator. I guess this is to avoid problems when an operator is added.

Personally, though, I'd do a reference check explicitly with ReferenceEquals.

查看更多
再贱就再见
7楼-- · 2019-02-12 17:46

Note that this is the VS 2005 documentation. I guess the folks who write the documentation also had the same question and couldn't come up with a good answer; the example was changed for VS 2008. Here is the current version:

public bool Equals(TwoDPoint p)
{
    // If parameter is null, return false.
    if (Object.ReferenceEquals(p, null))
    {
        return false;
    }

    // Optimization for a common success case.
    if (Object.ReferenceEquals(this, p))
    {
        return true;
    }

    // If run-time types are not exactly the same, return false.
    if (this.GetType() != p.GetType())
        return false;

    // Return true if the fields match.
    // Note that the base class is not invoked because it is
    // System.Object, which defines Equals as reference equality.
    return (X == p.X) && (Y == p.Y);
}
查看更多
登录 后发表回答