How difficult can it be to overload operator ==?

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

}

}

Comments

  • Anonymous
    November 20, 2007
    It's not difficult.  I'm not sure why people can't get it straight.

  • Anonymous
    November 20, 2007
    The comment has been removed

  • Anonymous
    December 02, 2007
    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.

  • Anonymous
    December 16, 2008
    The comment has been removed