afaolek
afaolek

Reputation: 8811

How does overloading the equality operator == really work?

I have this piece of code in MyClass:

public static bool operator ==(MyClass lhs, MyClass rhs)
{
    if (lhs == null || rhs == null)
        return false;

    // Other operations to check for equality
}

Going by the first line in the code, I'm comparing lhs and rhs to null. I'm not sure but I suppose that comparison itself will invoke the overload function again. And then we het to that line again, it invokes itself and so on. Sort of an infinite recursion.
But we all know that does not take place. This implies, in my opinion, that comparing with null does not invoke the equality overload. So what really occurs? How does comparing with null work?

Upvotes: 3

Views: 95

Answers (2)

D Stanley
D Stanley

Reputation: 152511

EDIT

I stand corrected. It does call the == operator recursively (at least in LinqPad 4.5) rather than binding to object.==. There are three ways to fix this:

  • Overload Equals instead if you really want value equality semantics.
  • Cast lhs and rhs to object
  • Use Object.ReferenceEquals as the MSDN guidelines recommend

I suppose that comparison itself will invoke the overload function again

No - null is not a MyClass so the call uses the default meaning of == which is reference equality.

Also note that the guidelines for overloading == state that it should only be overloaded for immutable types, since the expected behavior for == is reference equality which is what happens by default. Equals implies "value equality" semantics.

Upvotes: 5

Dmitrii Bychenko
Dmitrii Bychenko

Reputation: 186668

In addition to D Stanley answer. To avoid such kind of surprizes (Object operator == is called), use Object.ReferenceEquals when implementing ==:

public static bool operator ==(MyClass lhs, MyClass rhs)   
{
    // lhs and rhs are the same instance (both are null included)
    if (Object.ReferenceEquals(lhs, rhs))
      return true;
    else if (Object.ReferenceEquals(lhs, null) || Object.ReferenceEquals(rhs, null))
      return false;

    // From here we have different instances, none of them is null
    // Other operations to check for equality
}

Upvotes: 2

Related Questions