Equality Overloading and Code Analysis

One of the things I like about VS 2005 is the integration of FxCop functionality into the IDE. Most of the time, it informs me of better practices to things that I would have done differently in previous versions of .NET. A good example is the IsNullOrEmpty method on the String class. Code analysis pointed out that, for some of my code, this would be a better performing replacement for the

x == null or x == String.Empty

tests that are quite common on parameter validation.

One of the problems that I ran into, however, was when I was trying to correct a code analysis note about validating arguments. Specifically CA 1062 - Validate Arguments on Public Methods. I had a equality operator overload that looked like the following:

public static bool operator==(BusinessObject x, BusinessObject y)
{
 
  return x.Name = y.Name;
}

The code analysis complaint was that I should be validating the arguments of the public method. OK, I said, and modified the code to the following:

public static bool operator==(BusinessObject x, BusinessObject y)
{
   if (x == null)
      return false;

   if (y == null)
      return false;

   return x.Name = y.Name;
}

First off, the reason for the two if statements was because if I only used one, code analysis still complained. But what's worse is that when I ran my unit tests, I got a fatal exception saying that VSTestHost.exe had crashed. Walking through the code, I discovered a fatal oversight that caused the problem. Feel free to take a few seconds to consider the possibilities before reading the answer.

Figure it out?  It's much easier if you debug the app.

The problem is that the if (x == null) line introduces a stack overflow. This is because in order to evaluate whether x equals null, what does the code do? It calls the overloaded equality operator. Over and over again.

The solution is to modify how a null value is checked.

public static bool operator==(BusinessObject x, BusinessObject y)
{
   if (Object.ReferenceEquals(x, y))
      return true;

   if (Object.ReferenceEquals(x, null))
      return false;

   if (Object.ReferenceEquals(y, null))
      return false;

   return x.Name == y.Name;
}

Now you should be good to go.

Update: Corrected the fact that I can't write C# code without the benefit of a compiler :) See the comments for the rationale