Thursday, March 27, 2014

Get rid of deep null checks

Have you ever had to write a code like this one?

var store = GetStore();
string postCode = null;

if (store != null && store.Address != null && store.Address.PostCode != null)
     postCode = store.Address.PostCode.ToString();

I'm sure you have. We've all been there. 
The goal is to retrieve (or compute) a value, but in order to do that, we have to get through many intermediate objects, which could be in a default state. The aforementioned example is pretty easy. Sometimes, along the way, there are additional method calls, "as" conversions or collections. We have to handle properly each of them, which bloats further the code, making it less readable. There's got to be a better way.

 

Conditional extensions
Many developers found a solution in conditional extensions. If you google "c# deep null check" you will find several implementations. Their names vary, but the idea behind them is the same:

public static TResult IfNotNull<TResult, TSource>(
    this TSource source,
    Func<TSource, TResult> onNotDefault)
    where TSource : class
{
    if (onNotDefault == null) throw new ArgumentNullException("onNotDefault");

    return source == null ? default(TResult) : onNotDefault(source);
}

As you can see, the extension returns a value of TResult type. The source object is required to obtain the result. If the former is null, we are unable to do that, thus the method returns default value of TResult type. If it's not the case, we can safely invoke the onNotDefault delegate. 
After adding IfNotNull extension to our project, the first example can be rewritten in the following way:

var postCode =
    GetStore()
        .IfNotNull(x => x.Address)
        .IfNotNull(x => x.PostCode)
        .IfNotNull(x => x.ToString());