简体   繁体   中英

C# Overloading operator ==

//overloading operator ==
class Point
{
    private int m_X,int m_Y;

    public static operator == (Point p1 ,Point p2)
    {
        if(object.ReferenceEquals(p1,p2)
            return true;

        if((object)(p1) == null) || ((object)(p2) ==null)
            return false;

        return( (p1.x == p2.x) && (p1.x == p2.x));
    }

    //overloading the != operator
}
  1. Is it necessary to override the Equals function
  2. if the p1 and p2 is not typecasted to object , stack overflow exception is thrown Why we need to the Point objects to typecast to object.
  1. It is generally a good idea to override the Equals() method if you overload the == operator, because they should return the same result, and Object.Equals() will defer to ReferenceEquals() if you do not override it so the operator and method will have different outcomes. The easy way to do that is to have the operator call the Equals() method (which should have similar code as you have here)

  2. You must cast to Object to perform the == null comparisons, because you're in the overloaded == method, and so without a cast to a base type your operator method is calling itself endlessly to try to evaluate whether p1 == null .

In Guidelines for Overriding Equals() and operator == , it says:

A common error in overloads of operator == is to use (a == b), (a == null), or (b == null) to check for reference equality. This instead results in a call to the overloaded operator ==, causing an infinite loop. Use ReferenceEquals or cast the type to Object, to avoid the loop.

1) It is not strictly necessary to overload .Equals(), but it is considered good coding practice to do so. You generally don't want .Equals() to do reference comparisons and operator == to do value comparisions. You should also override GetHashCode and operator!=.

2) The stack overflow occurs because you are calling your own operator== over and over again. The compiler has two choices when the casts are not present:

  1. Use your implementation of operator==(Point, Point)

  2. Use Object's operator==(object, object)

Because #1 is more specific, the compiler chooses your implementation. Explicilty casting both to object ensures that Object's implementation of operator== is called. You could achieve the same thing without the cast with the following code:

if (Object.Equals(p1, null) || Object.Equals(p2, null))

1 - It is not necessary, altough it would be nice. In fact, the behavior you're trying to implement in the operator is commonly put on the Equals method.

2 - If you don't do the cast, p1 == null will call the operator itself, thus causing the stackoverflow.

This link points to the MS guidelines for overriding Equals and ==.

To answer your first question: It's not technically mandatory, but if you don't override Equals , it will do what the == operator originally did: refer back to the System.Object version, which checks to see if the references are the same. So if you want Equals to do the same thing as == , you have to override that too. Check out " When should I use == and when should I use Equals? " From that article:

For reference types where == has not been overloaded, it compares whether two references refer to the same object - which is exactly what the implementation of Equals does in System.Object.

The answer to your second question is that if you don't cast them back to object , there will be an infinitely recursive call to your == operator when you evaluate p1 == null . See it? You'd be calling == inside itself, since p1 is a Point and this is the Point class's == operator. Instead, what you want to do on that line is determine whether the two references are null, which the System.Object version of the operator will do.

The stack overflow exception is probably because using == on p1 calls your == operator again, endlessly.

Overriding the == operator in this case is a good idea.

You would benefit from further studying the difference between == and .Equals() as well as the difference between Value and Reference types ( Point is a struct , meaning it is a Value type).

Your current override essentially combines reference and value equality checks--making it combine the behaviors of == and .Equals() .

Regarding your second question, your == overload calls itself (the == operator is used within the overload). Another aspect to consider is that Point is a value-type, and therefore can never be null (unless it's wrapped in Nullable<Point> ).

I agree that overriding == is probably the way to go. But you can clean up a lot of this code by making it a struct instead of a class . You won't have to worry about null checks, and it will make more logical sense since it really is a "value".

As the others have said, it is not strictly necessary to override .Equals(object o) if you create an == operator but it is preferred. In addition, the compiler will generate a couple of warnings if you do not.

warning CS0660: '<Type>' defines operator == or operator != but does not override Object.Equals(object o)
warning CS0661: '<Type>' defines operator == or operator != but does not override Object.GetHashCode()

Thus even the compiler points you towards overriding .Equals(Object o) and having == defer to that.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM