On accessing chains of potentially null properties

Raise your hand if you’ve ever written code looking like this:

var result = default(int);
if (fubar != null) {
var foo = fubar.Foo;
if (foo != null) {
var bar = foo.Bar;
if (bar != null) {
result = bar.Baz;
}
}
}

We’ve all done that, and it’s just sad. There seems to be a law of the Universe that says that if your code looks like a wedge, like the code above, then something is wrong with that code, or with the language it’s expressed in. It illustrates one of the reasons why Tony Hoare, inventor of Quicksort, called the null reference his “billion-dollar mistake”.

One can mitigate this to a degree, and use ternary operators, to make the code a little bit less horrible (but not that much):

var foo = fubar == null ? null : fubar.Foo;
var bar = foo == null ? null : foo.Bar;
var result = bar == null ? default(int) : bar.Baz;

Or maybe you’ve just given up, just call

fubar.Foo.Bar.Baz

and accept the null ref exceptions. Why don’t you also wear sweat pants while you’re at it?

Of course, the more theoretically-oriented of you will have immediately objected that for our code to attempt to reach deep into the object graph and grab Baz is in direct violation of the Law of Demeter. Right. But in reality, we deal with DOMs, JSON payloads, and other deep graphs that are designed to be traversed, all the time, and it would be impractical to be too dogmatic about this.

Ideally, we would have language support for this, and it seems like we will, in the next version of C#:

fubar?.Foo?.Bar?.Baz

In the meantime, what can we do?

Don’t we have a language construct that enables us to express code without immediately executing it? Well, yes we do: Lambdas and expression trees!

I’ve built a little helper that takes an expression tree, and evaluates it on an object, but doing null checks on the way. Using it is as simple as this:

var result = fubar.Get(f => f.Foo.Bar.Baz);

If you don’t even know if the fubar object is null, you can use it as a static method:

var result = NotNull.Get(fubar, f => f.Foo.Bar.Baz);

Here is the source code for the helper:

using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Reflection;

namespace Bleroy.Helpers {
public static class NotNull {
public static TProp Get<TSource, TProp>(
this TSource source, Expression<Func<TSource, TProp>> property)
where TSource : class {

if (source == null) return default(TProp);
var current = property.Body;
var properties = new List<PropertyInfo>();
while (!(current is ParameterExpression)) {
var memberExpression = current as MemberExpression;
if (memberExpression == null || !(memberExpression.Member is PropertyInfo)) {
throw new InvalidOperationException("All members in the expression must be properties.");
}
properties.Add((PropertyInfo) memberExpression.Member);
current = memberExpression.Expression;
}
properties.Reverse();
object currentValue = source;
foreach (var propertyInfo in properties) {
if (currentValue == null) return default(TProp);
currentValue = propertyInfo.GetValue(currentValue);
}
return (TProp) currentValue;
}
}
}

I’ve also posted this on Github as a Gist:
https://gist.github.com/bleroy/11131888

Of course, the code in this post comes with no guarantee of anything whatsoever, especially performance and I don’t recommend anybody use it. It’s a fun experiment, is what it is. I’d love to read your thoughts about it in the comments section.

Note: in Clay, we’ve copied Ruby’s Nil behavior, and it is possible to safely access deep properties without caring too much about them being null. This is nice, but doesn’t help you much if you’re using regular C# objects.

Update: I'm being pointed to Monads.Net, that is a set of monad-driven helpers, one of which addresses the same problem with a similar solution. With Monads.Net, you'd write:

var result = fubar.With(f => f.Foo).With(f => f.Bar).With(f => f.Baz);

I prefer my version, because I don't need to use one method call and one Lambda per property, but can instead use one big deep Lambda. It's nice too see others come to the same kind of solution however.

Update 2: Ian Griffiths was there years ago: his version rewrites the expression tree.

17 Comments

  • You should check out Monads.net --> https://github.com/sergun/monads.net

  • >I don't need to use one method call and one Lambda per property, but can instead use one big deep Lambda
    Talk about premature diminishment... (like premature optimization, but makes everything much slower.)
    Have you timed these two solutions (Bleroy.Helpers.NotNull.Get and Monads.Net)? I think that yours is ~1000 times slower.

  • As I said in the post: "Of course, the code in this post comes with no guarantee of anything whatsoever, especially performance and I don’t recommend anybody use it. It’s a fun experiment, is what it is."

  • I assume that using Roslyn one could have the Nil Behavior in a per project basis that would convert it to the nested loop pattern.

  • This solution is also pretty elegant: http://geekswithblogs.net/nabuk/archive/2014/03/26/get-rid-of-deep-null-checks.aspx

  • In my tests, this "hidden sweatpants" edition is about 20x faster :)

    public static class NotNullSweatpants
    {
    public static TProp Get(
    this TSource source, Func property)
    where TSource : class
    {
    try
    {
    return property(source);
    }
    catch (NullReferenceException)
    {
    return default(TProp);
    }
    }
    }

    (Also just a fun experiment)

  • Rob: cool that it's faster, but catching null refs does not give the same behavior. It will hide any legitimate exceptions that may happen inside the property getters. Not to mention that using try/catch as flow control is icky. If you're after perf, there are probably better optimizations to be found, such as creating expressions for each step, or even injecting the null checks right into the original expression, and then caching the resulting expression.

  • The Roslyn team is considering a "null propagating operator" that would solve this problem on the language level (http://roslyn.codeplex.com/discussions/540883).
    But for now your code looks like a nice way to remove some clutter.

  • Jasper: mention of the feature and the link to that forum post were already in the post... Read more closely ;)

  • Oops, that's embarrassing. Indeed, I should have paid more attention to your introduction.

  • This seems rather familiar...just over 6 years ago I wrote a similar sort of feature: http://www.interact-sw.co.uk/iangblog/2008/04/13/member-lifting

    Mine works a little differently: it rewrites the expression tree rather than evaluating it. That has a couple of useful properties. First, you can go on to use the modified expression for other things. But more importantly, it lets you compile the expression. For one-off execution that slows you down massively of course, but if you can amortize the costs over multiple executions, it can make things much faster.

    I also highly recommended never using this in production code... In fact, I concluded that it really needed to be an intrinsic language feature.

  • Although I've occasionally needed to traverse a deep path that could have null at any point, its always been in relation to code that is quite questionable.

    Adding a null-don't-care operator won't affect me much but I do feel that it will be more often used to create bad code than it will be used for good reason.

  • I took a still different approach in my (still young) ProxyFoo library. It has some drawbacks because you can't proxy a concrete class, but it should be extremely fast. You can workaround this by creating a duck proxy first and using an interface to "duck cast" the return type to. Eventually, I would want to round out the library to be able to apply this to something like Json (or any dynamic) content so that you can get the convenience of using an interface to access it.

    See http://proxyfoo.com/docs/safeproxies/

  • Andrew: that's why I mentioned the Law of Demeter, and also a couple of examples where it's debatable at best that it applies. Phil has a great post about this: http://haacked.com/archive/2009/07/14/law-of-demeter-dot-counting.aspx/

  • I would like to see the look on C# creators faces who witness such language features overuse. Lambdas are super useful but methods as NotNullSweatpants are just ridiculous (the same goes for unnecessary use of var keyword)...

  • I would say that LoD is "neither here nor there", but I realize it might be important for some to be able to cite.

    I once saw a team use struts instead of classes in VB.net because "that way we don't need to check for null"




  • This is fun. Keep it coming.

    @seniordev: I could try to drag a member of the C# team into the conversation, but I'm not sure it's necessary. Anders for example uses the var keyword a lot, as can be verified in numerous talks and videos he gave. Eric Lippert sums it up nicely here: http://blogs.msdn.com/b/ericlippert/archive/2011/04/20/uses-and-misuses-of-implicit-typing.aspx Can you show what an unnecessary use of var looks like?
    On Lambdas, please explain how this is overusing them?

Comments have been disabled for this content.