While digging through C# syntax trees, I came across an old problem in C# development that I call the ‘if null’ problem. This problem is exemplified in the following piece of code:

protected override bool IsAvailable(JetBrains.ReSharper.Psi.Tree.IElement element)
{
  var uns = GetSelectedElement<IUsingNamespaceDirective>(true);
  if (uns != null)
  {
    // assuming we're not in a namespace
    var ns = uns.GetContainingNamespaceDeclaration();
    if (ns == null)
    {
      var file = uns.GetContainingFile() as ICSharpFile;
      if (file != null)
      {
        if (file.NamespaceDeclarations.Count == 1)
        {
          from = uns;
          to = file.NamespaceDeclarations[0];
          return true;
        }
      }
    }
  }
  return false;
}

Can you see the onslaught of null checks up here? Wonder if there’s a cleaner way to write the same piece of code? There sure is. Using the power of extension methods, we simply define a few extensions in order to guarantee that evaluations only propagate on non-null objects. Here’s the full listing:

public static class FluentExtensions
{
  public static TResult With<TInput,TResult>(this TInput o, Func<TInput,TResult> evaluator)
    where TResult:class
  {
    if (o == default(TInput)) return null;
    return evaluator(o);
  }
  public static TInput If<TInput>(this TInput o, Func<TInput, bool> evaluator) 
    where TInput : class
  {
    if (o == nullreturn null;
    return evaluator(o) ? o : null;
  }
  public static TResult Return<TInput,TResult>(this TInput o, 
    Func<TInput, TResult> evaluator, TResult failureValue) where TInput: class
  {
    if (o == nullreturn failureValue;
    return evaluator(o);
  }
  public static TInput Do<TInput>(this TInput o, Action<TInput> action) 
    where TInput: class
  {
    if (o == nullreturn null;
    action(o);
    return o;
  }
}

This generic-heavy code offers several methods: you have With() which keeps the ‘context’ of the evaluation, If() to check on predicated, Do() when you just want to execute something, and Return() when you’re done.

So the chunk of code I showed earler can be refactored to look as follows:

protected override bool IsAvailable(JetBrains.ReSharper.Psi.Tree.IElement element)
{
  return this.With(x => GetSelectedElement<IUsingNamespaceDirective>(true))
    .Do(x => { from = x; })
    .If(x => x.GetContainingNamespaceDeclaration() == null)
    .With(x => x.GetContainingFile() as ICSharpFile)
    .If(x => x.NamespaceDeclarations.Count == 1)
    .Do(x => { to = x.NamespaceDeclarations[0]; })
    .Return(x => truefalse);
}

The above piece of code is cleaner and more readable, and the null checks are abstracted away by the infrastructure. ■