The War On Nulls

As .NET developers, we’ve all seen this exception hundreds of times: “System.NullReferenceException – Object reference not set to an instance of an object”. In .NET, this exception occurs when trying to access a reference variable with a null value. A null value means the variable does not hold a reference to any object on the heap. It is one of the most frustrating and prolific errors that we programmers encounter. But it needn’t be this way! We can prevent this error by following a few simple rules. But first, a little history…

The null reference was invented by Tony Hoare, inventor of QuickSort, one of the world’s most widely used sorting algorithms. In this introduction to his talk at QCon 2009, Tony describes the impact the null reference has had on software:

I call it my billion-dollar mistake. It was the invention of the null reference in 1965. At that time, I was designing the first comprehensive type system for references in an object oriented language (ALGOL W). My goal was to ensure that all use of references should be absolutely safe, with checking performed automatically by the compiler. But I couldn’t resist the temptation to put in a null reference, simply because it was so easy to implement. This has led to innumerable errors, vulnerabilities, and system crashes, which have probably caused a billion dollars of pain and damage in the last forty years. In recent years, a number of program analysers like PREfix and PREfast in Microsoft have been used to check references, and give warnings if there is a risk they may be non-null. More recent programming languages like Spec# have introduced declarations for non-null references. This is the solution, which I rejected in 1965.

So obviously null references have caused quite a lot of damage. But neither Tony or null references are to blame. It’s the careless use of null references that has made them as damaging and prolific as they are.

I can’t think of a single reason why you would need to use null references as part of your system design. Here are some tips for preventing null references in your system.

Never use null references as part of the design

Business logic should not be based around testing for null references. If an object requires an empty state, be explicit about it by creating an empty representation of the object. You can then check if the object is in an empty state by comparing the current instance to an empty instance.

Here is an example of some code that uses a generic interface called ICanBeEmpty to support an empty representation of a Customer object. An extension method called HasValue() allows us to check if an object represents an empty instance.

public class Customer : ICanBeEmpty<Customer>
{
    private int id;
    private string name = string.Empty;
    //...
 
    public bool Equals(Customer other)
    {
        return this.id == other.id;
    }
 
    public static Customer Empty
    {
        get { return new Customer(); }
    }
 
    Customer ICanBeEmpty<Customer>.Empty
    {
        get { return Empty; }
    }
}
 
public interface ICanBeEmpty<T> : IEquatable<T>
{
    T Empty { get; }
}
 
public static class Extensions
{
    public static bool HasValue<T>(this ICanBeEmpty<T> obj)
    {
        return obj.Equals(obj.Empty);
    }
}

Don’t accept null references as parameters

Guard statements are often used to check for null references in methods. If you design your system not to pass nulls, you won’t need guards to check for null in your methods. But when you can’t guarantee input to your public methods, then you need to be defensive about null references.

Don’t return null references

A call to a method or property should never return a null reference. Instead, return an empty representation of an object, or throw an exception if a non-empty value is expected.

Fail fast if a null reference is detected

Design-by-contract technologies, such as Spec#, have declarations that can check for null references at compile time. You can also use an aspect-oriented programming (AOP) solution, such as PostSharp, to create custom attributes that ensures an exception is thrown if any null references are passed in, or returned by a method at runtime. By throwing an exception as soon as a null reference is detected, we can avoid hunting through code to find the source of a null reference.

public class CustomerRepository
{
    [DoesNotReturnNull]
    public Customer GetCustomer(int id)
    {
        //...
        return Customer.Empty;
    }
 
    [DoesNotAcceptNull]
    public void SaveCustomer(Customer customer)
    {
        if (customer.HasValue())
        {
            //...
        }
    }
}

Wrap potential sources of null references

If you are using a third-party service or component where you might receive a null reference, then wrap the call in a method that handles any null references to ensure they don’t leak into the rest of the system.

Always ensure object members are properly instantiated

All object members should be instantiated when an object is created. Be careful with strings in C#, as these are actually reference types. Always set string variables to a default value, such as string.Empty.

Nullable value types are ok

The nullable value types introduced in C# 2.0, such as int? and DateTime?, are better at handling null references as you have to explicitly cast them to a non-null value before accessing them. Be careful with using the Value property on a nullable type without first checking if the variable has a non-null value using the HasValue property. You can use GetValueOrDefault to return a default value if the variable is null.

By limiting the use of null references and not letting them leak into other parts of the system, we can prevent the troublesome NullReferenceException from ruining our day.

Advertisements

8 Responses to “The War On Nulls”


  1. 1 Tobin Harris February 1, 2009 at 8:20 pm

    Very amusing history, thanks!

    I’m sold on your mission, but not the implementation yet 🙂 On first glance, there seem to be too many moving parts. Also, would be interesting to see this compared to the Null Object pattern.

  2. 2 timross February 1, 2009 at 11:27 pm

    Hi Tobin, the Null Object pattern is certainly a good way to represent a null object state. The main difference between Null Object and the Empty Object approach is that with Null Object you create a derived class that overrides calls to its parent class, e.g. NullCustomer that derives from Customer. You can then use the null object in place of the actual object. The Empty Object approach uses the state of an object to determine if a value has been set.

    I would use Null Object if I had code that expected an object, but I didn’t want to use the real object. I would use Empty Object if I simply needed to check if an object has an empty value.

    I have successfully used the Empty Object approach on DTO classes to ensure that the entire data structure is properly instantiated, but that the objects can be tested for an empty state.

  3. 3 zubairk February 2, 2009 at 10:39 am

    I totally agree Tim, never design for nulls. That’s just crazy annoying. Guard statements also annoy me, though I guess they are needed on a public api.
    I find Null Objects are very neat solutions for these problems.
    Your ICanBeEmpty implementation is novel, allowing for the equal operator / function to be used to compare an object to its empty state.
    I wouldn’t say Nullable types are any better. They seem to just extend a hand to lazy programmers that like Nulls or even make it easier for the database schema to leak into your domain.

  4. 4 timross February 2, 2009 at 11:16 am

    That’s very true, Zubair. I don’t often use nullable value types, but the nullable DateTime does come in handy sometimes.

  5. 5 Mike Wagg February 2, 2009 at 8:18 pm

    I like your solution in the DTO example as I’ve felt the pain of working with a structure that can blow up in your face at any point.

    In terms of nulls in general, I think my biggest area to focus on is not letting nulls from external components leak into your code.

  6. 6 Tim Macfarlane February 27, 2009 at 10:09 am

    Hi Tim, it never ceased to amaze me that a language designed in the late 90s should maintain support for nulls… but we have what we have. Anyway, here’s perhaps a simpler implementation of an “optional” reference:

    struct Optional where T : class {
    public T Value { get; private set; }

    public static implicit operator Optional (T o) {
    return new Optional {Value = o};
    }

    public static implicit operator T (Optional o) {
    if (o.HasValue) {
    return o.Value;
    } else {
    throw new NullReferenceException(“optional value not set”);
    }
    }

    public bool HasValue {
    get {
    return Value != null;
    }
    }
    }

    Complete with implict casts so it doesn’t get in your way. The Optional class then just becomes an annotation of your variables – you use it to document variables to say “this one’s optional” in the domain sense. Of course, if you cast bask to a T, you’ll get a NullReferenceException if the value is null. So you should get early warning, and there’s a HasValue property for explicit checks, which you’ll want to do for a value that’s optional.

  7. 7 Tim Macfarlane February 27, 2009 at 10:14 am

    Oops, seems my code’s been escaped out, here it is again:

    struct Optional<T> where T : class {
    public T Value { get; private set; }

    public static implicit operator Optional<T> (T o) {
    return new Optional<T> {Value = o};
    }

    public static implicit operator T (Optional<T> o) {
    if (o.HasValue) {
    return o.Value;
    } else {
    throw new NullReferenceException(“optional value not set”);
    }
    }

    public bool HasValue {
    get {
    return Value != null;
    }
    }
    }

  8. 8 timross February 27, 2009 at 2:08 pm

    Hi Tim, that looks like a great solution, thanks!


Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s





%d bloggers like this: