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