How difficult can it be to overload operator ==?

How difficult can it be to overload operator ==?

  • Comments 4

Well apparently very difficult! Today, I read article after article on blogs that suggested weird and wonderful ways of overloading the operator == in C#. Almost all of those were incorrect! So I set myself a challenge to put the record straight:

Before showing you the code, a number of things to remember:

-          Overriding operator == is a feature of the C# language and there is no equivalent for it in the Intermediate Language (IL). In other words, the compiler replaces operator == with method calls to the operator overload’s static method.

-          Any type that overloads operator == should also overload operator !=

-          It only makes sense to override both Equals and GetHashCode methods when overloading operator ==.

-          Just to put the record straight, if the GetHashCode of two objects of the same type return the same value, it does NOT mean they are equal!

-          Also remember, if you are overloading operator ==, avoid using operator == in its implementation. You will probably get stock in an infinite recursion.

-          ReferenceEquals and cast to object should be your friends to avoid recursion and calls to unwanted methods (i.e. You probably don’t want to call operator == overload from the Equals method when evaluating something like obj == null)

-          You need to look after null values!

-          Use the static Object.Equals method in operator == and != overloads to avoid needing to overload  operator == for each inheritor of your class (The instance Equals method is virtual)

So here is an example:

class Rectangle

{

   private readonly int _x;

   private readonly int _y;

 

   public Rectangle(int x, int y)

   {

      _x = x;

      _y = y;

   }

 

   public override int GetHashCode()

   {

      return _x ^ _y;

   }

 

   public override bool Equals(object obj)

   {

      if (ReferenceEquals(obj, this))

         return true;

 

      Rectangle rect = obj as Rectangle;

 

      // need to use ReferenceEquals or cast rect to object

      // to avoid a call to the == operator overload below

      if (ReferenceEquals(rect, null))

         return false;

 

      return rect._x == _x && rect._y == _y;

   }

 

   public static bool operator ==

      (Rectangle r1, Rectangle r2)

   {

      // use Object.Equals to avoid needing to to provide == operator

      // overload for all inheritors of this class

      return Object.Equals(r1, r2);

   }

 

   public static bool operator !=

      (Rectangle r1, Rectangle r2)

   {

      return !Object.Equals(r1, r2);

   }

}

Leave a Comment
  • Please add 8 and 2 and type the answer here:
  • Post
  • It's not difficult.  I'm not sure why people can't get it straight.

  • GetHashCode() must always return same value for a given object. Otherwise, it will break any hash table you put it in. Unless you have a non-mutable field to work with, overriding == safely just isn't possible.

    Pedram: You are absolutely correct!

  • I think I have only seen operator overloading at uni, even there purists were saying that we should never do it as it opens the window to many mistakes, as you have said, during design but also during implementation as loses the object predictability.

    I tend to implement IComparer if I need to do some funky value comparison as it is cleaner and more predictable.

  • Why don't you add method "public bool Equals(Rectangle obj)"? This method can be defined without casts. Then this method can be used in overloaded Equals and definition of operators. I think, it is faster solution.

    Another problem can be with line: "Rectangle rect = obj as Rectangle;" and not sealed Rectangle class. Imagine situation when there exists "class MyRectangle : Rectangle" and you pass instance of this MyRectangle class into Rectangle.Equals method. It can return true, but in reality it is not so easy to say if it is true.

    Next problem is with Equals on struct, where you should avoid boxing.

Page 1 of 1 (4 items)