Welcome to MSDN Blogs Sign in | Join | Help
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.

Posted: Friday, February 29, 2008 4:18 AM by AlexJ
Filed under: , ,

Comments

MatthieuMEZIL said:

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.

# February 29, 2008 4:51 AM

Matthieu MEZIL said:

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

# February 29, 2008 5:15 AM

XIU said:

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);

}

# February 29, 2008 5:42 AM

Michel Perfetti [Miiitch] said:

Que les puristes de la performance soient rassurés, le reste du post n'est que pour le fun :) En discutant

# February 29, 2008 10:18 AM

AlexJ said:

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

@Michel: that is pretty cool.

# March 3, 2008 1:33 PM

Meta-Me said:

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

# March 3, 2008 1:47 PM

Noticias externas said:

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

# March 3, 2008 2:13 PM

macsgold said:

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.

# March 7, 2008 12:22 AM
Anonymous comments are disabled
Page view tracker