Maybe I’m just a little slow…


But I only just realized that extension methods are cool for avoiding NullReferenceExceptions.

We all know that if you have something like this:

LicensePlate
licensePlate = null;
Car car = licensePlate.Car;

It will throw a NullReferenceException. However if you have an extension method

public static Car GetCar(this LicensePlate
lp);

we can call it like this:

Car car = licensePlate.GetCar();

And we can still handle the fact that ‘licensePlate’ is null gracefully. i.e.

public static Car GetCar(this LicensePlate
lp)
{
    if
(lp == null) return
null;
    return
lp.Car;
}

Now imagine you wanted to chain a whole series of calls something like this:

string
code = licensePlate.Car.Owner.Address.PostCode;

That is incredibly unsafe, because any one of those properties could potentially return null.

To get around that you could use a general purpose extension method using generics, to allow you to go through a set of arbitrary translations, anyone of which could do nasty things like return null:

public static V Maybe<T, V>(this
T t, Func<T, V> selector)
            where
T : class
           
where
V : class
{
    if
(t == null) return
null;
    return
selector(t);
}


Now you can use this to chain a whole load of unsafe methods together.

string
code = licensePlate.Maybe(lp => lp.Car)
                          .Maybe(c
=> c.Owner)
                          .Maybe(o
=> o.Address)
                          .Maybe(a
=> a.PostCode);

It looks a lot like the Maybe monad (hence the name). The interesting thing though, is that if you implement your methods as extensions methods rather than instance methods, you can wire this sort of thing in so easily, without needing to use lambdas at all.

i.e. so rather than this which is unsafe:

string
code = licensePlate.Car.Owner.Address.PostCode;

of this which is ridiculously cumbersome and hard to read:

LicensePlate
licensePlate = null;

Car car = null;

Person owner = null;

Address address = null;
string
code = null;

if
(licensePlate != null)
{
    car = licensePlate.Car;
    if (car != null)
    {
        owner = car.Owner;
        if
(owner != null)
        {
            address = owner.Address;
            if
(address != null)
            {
                code = address.PostCode;
            }
        }
    }
}

or this which is a little complicated for anyone uncomfortable with lambdas:

string
code = licensePlate.Maybe(lp => lp.Car)
                          .Maybe(c
=> c.Owner)
                          .Maybe(o
=> o.Address)
                          .Maybe(a
=> a.PostCode);

you could write this:

string code =
licensePlate.GetCar().GetOwner().GetAddress().GetPostCode();

Which is almost as easy to read as the original version. But much safer.

All you have to do is write your extension method to handle nulls.

Sometimes the coolest things are right under your nose.

Comments (9)

  1. Hello Alex,

    I love it! 🙂

    If I remember well, I have readen an article in which they say that in C#4, we will have an operator ?. which do what you do with extension methods.

  2. Qui n’a jamais fait quelque chose comme ça: LicensePlate licensePlate = null ; // Récupérer une instance

  3. xiu@shoeke.com says:

    I made the same method just a few days ago (just called it IfNotNull but Maybe actually sounds better :P). Only difference is that I didn’t use the constraint on V.

    public static V Maybe<T, V>(this T t, Func<T, V> selector)

               where T : class

    {

       return t != null ? selector(t) : default(V);

    }

  4. Que les puristes de la performance soient rassurés, le reste du post n’est que pour le fun 🙂 En discutant

  5. Alex D James says:

    @XUI: obviously great (excuse the self congratulation) minds think alike.

    @Michel: that is pretty cool.

  6. Meta-Me says:

    Michel Prefetti , has taken my little Maybe thingie and taken it a lot further , by using expression

  7. Michel Prefetti , has taken my little Maybe thingie and gone a lot further , by using expression tree

  8. macsgold says:

    Eeek, changing the ‘intuitive C# behavior’ of code will get you into trouble sooner rather than later.  If ‘acquired intuition’ says that x.M() throws a Null ref if x==null then change this behavior at your own risk.  If I see a line x.M() I’d feel safe using "x.ToString()" on the next line but your way would make a fool out of me.  It should be a golden rule of extension methods: throw null ref if the object is null.  One day we may get ‘not null object types’ but extension are not the answer.