May 7, 2009

Fancy ways of checking for null parameters in C#

Having programmed in C++ for many years it happens every now and then that I write C# code like this:

public void MyMethod(Test test)
{
if (!test)
{
throw new ArgumentNullException("test");
}
...

This of course doesn't compile as test cannot be cast to bool.
The obvious way of doing it (i.e. if (test == null) ...) is not really much of a problem, but nevertheless I played around a bit to see if there are other methods of doing it and maybe get my C++ inspired code to work.

Helper Class with Conversion Operators

Have a look at the following helper class.

public class IsNull
{
private readonly bool value;

private IsNull(bool value)
{
this.value = value;
}

public static explicit operator IsNull(Test o)
{
return new IsNull(o == null);
}
public static bool operator true(IsNull t)
{
return t.value;
}
public static bool operator false(IsNull t)
{
return !t.value;
}
public static bool operator !(IsNull t)
{
return !t.value;
}
}

Using it we can rewrite our test like this:

if ((IsNull)test)
{
throw new ArgumentNullException("test");
}

Hmm, the code looks a bit strange and it's not really obvious what's going on.
The IsNull class implements a custom conversion operator from type Test. So the cast creates a new IsNull object which stores if the passed object was null or not. The class also has overloaded true and false operators which allows the object to be used as an expression for the if statement.

This approach has one big problem: You cannot create conversion operators from type object. The example above only works with objects of type Test. You would either have to add a conversion operator for each type (yuck...) or do it for a common base class (but then it won't work for classes implemented by others).

Overloading true and false Operators

As we've seen in the example above the true and false operators can be overloaded for the object to be used as a Boolean expression. This of course can be done with the Test class too:

public class Test
{
public static bool operator true(Test t)
{
return t != null;
}
public static bool operator false(Test t)
{
return t == null;
}
public static bool operator !(Test t)
{
return t == null;
}
...
}

Now this allows us to get my pseudo C++ code compile:

if (!test)
{
throw new ArgumentNullException("test");
}

I didn't mention it above, but you also have to implement the negation operator to make the ! notation work.

So we have what we wanted, but the approach has the same problem as the one before: you have to do it for all classes you want to use it for... :-(

So let's try something else...

Using Extension Methods

Extension methods are a neat way to add methods to classes. You can even extend object. Let's try the following:

public static class ObjectExtensions
{
public static bool IsNull(this object o)
{
return o == null;
}
}

This allows us to write the following:

if (test.IsNull())
{
throw new ArgumentNullException("test");
}

On first glance this code seems to be complete nonsense as you cannot call a method on an object reference that is null. But using the extension method approach which is implemented as a static method, it really works.

Useful? Probably not so much.
But you could do the following:

public static class ObjectExtensions
{
public static void ThrowIfNull(this object o, string paramName)
{
if (o == null)
{
throw new ArgumentNullException(paramName);
}
}
}

This allows you to do the null check and the exception throw in one simple step:

test.ThrowIfNull("test");

Quite handy, right?
Finally this blog post has some useful content... ;-)