What Is A NullReferenceException And How Do I Fix It?

TLDR;

You get a NullReferenceException when your code is trying to use a null variable. You’re either calling a method on that variable or accessing a property or something else.

The problem is that there’s nothing to call upon to begin with. Either you have never assigned anything to that variable or you have set it to null yourself before trying to use it. Or some external code is returning a null to you, which you are not validating before you using it.

There are many reasons for this exception to pop up…

Example?

Look:

string whatever = null;
whatever.ToCharArray(); // boom

This throws:

System.NullReferenceException: Object reference not set to an instance of an object.

See that? You can’t call ToCharArray() there because there’s no string instance to call upon in the first place. It’s a null. The house is there but the lights are off and there’s no one home.

How do I find it?

More often than not, the runtime will tell you what line exploded. That is, if you’re running your code in debug mode. If you get this error on production code, you will at the very least have the call stack included in the full error message. Use the call stack to navigate to the failing method in your code base. Then set a break point there and repeat the scenario that led the code to explode, running the code line-by-line from your breakpoint.

What should I watch out for and avoid?

Some coding anti-patterns are just asking for it.
Here are some examples of dodgyness to watch out for and ways to stamp it out.

Method Parameters

Nothing guarantees your method’s caller will provide all parameters…

static void Main()
{
    string message = null;
    Log(message);
}

static void Log(string message)
{
    var length = message.Length; // boom
}

To avoid this, check for parameters you absolutely require and throw the ball back to the caller…

static void Log(string message)
{
    if (message == null)
    {
        throw new ArgumentNullException("message");
    }

    var length = message.Length; // boom
}

Chaining Accessors

Look at this:

public class Car { public Engine Engine { get; set; } }
public class Engine { public SparkPlug SparkPlug { get; set; } }
public class SparkPlug { public void MakeSpark() { } }

static void Main()
{
    var car = new Car();
    car.Engine.SparkPlug.MakeSpark(); // boom
}

You’re chaining property getters without checking if any of those properties are null. Any of those gets can return null and acting upon the null will make things go boom.

You have different ways to avoid this situation.

If you enjoy typing, you can check for every single accessor…

if (car != null)
{
    if (car.Engine != null)
    {
        if (car.Engine.SparkPlug != null)
        {
            car.Engine.SparkPlug.MakeSpark();
        }
    }
}

… but that’s a lot of typing.

Instead, you can short-circuit them in an if statement…

if (car != null && car.Engine != null && car.Engine.SparkPlug != null)
{
    car.Engine.SparkPlug.MakeSpark();
}

… but that’s still a lot of typing.

If you’re not having to maintain some old code and you have at least C# 6, then you can use the safe navigation operator…

car?.Engine?.SparkPlug?.MakeSpark();

… which is great and tight, except you won’t know whether the MakeSpark() method was called or not.

Which is why you may want to go with this instead:

var sp = car?.Engine?.SparkPlug;
if (sp != null)
{
    sp.MakeSpark();
}
else
{
    // panic
}

No Instance At All

When you declare a reference type member field, it has the default value of null, unless you say so otherwise.

private static string message;
static void Main()
{
    message.ToCharArray(); // boom
}

Your defense here is the same as before.

if (message != null)
{
    message.ToCharArray();
}

Using as Casting Operator

The as casting operator tests if casting is possible and returns null if not.

object whatever = "whatever"; // okay
Car car = whatever as Car; // okay
car.ToString(); // boom

Again, test for null.

object whatever = "whatever";
Car car = whatever as Car;
if (car != null)
{
    car.ToString();
}

Indexing

Arrays themselves are nullable objects.
If an array variable is null, there’s nothing to index.

Car[] cars = null;
cars[0].ToString(); // boom

Sizing an array only makes space for its items.
It does not instantiate them, so are spots are null.

Car[] cars = new Car[10];
cars[0].ToString(); // boom

Jagged arrays are arrays in which each element references another array.
That reference is the same as any other reference, so it can be null.
If it’s null, there’s nothing to index.

Car[][] cars = new Car[10][];
cars[0][0] = new Car(); // boom

Lists and other indexable collections are no different.
If there is no instance, there’s nothing to index.

List<Car> cars = null;
Car car = cars[0]; // boom

The solution to all of these is the same yet again.
Check for nulls before using anything.

foreach

If your enumeration is null, there is nothing to enumerate.

List<Car> cars = null;
foreach (Car car in cars) // boom
{
}

You know what to do.

LINQ Expression

LINQ expressions don’t execute right away, so they don’t explode when you declare them.
Instead, they wait for you to call a materializer such as ToArray().
If your expression accesses null variables, it will go boom only when you execute it.

var cars = new List<Car>() { null };
var query = cars.Select(c => c.Engine); // c can be null
var engines = query.ToArray(); // boom

To protect against this, you can check for nulls inside the projection, and even remove them if you want to.

var cars = new List<Car>() { null };
var query = cars.Select(c => c?.Engine).Where(e => e != null);
var engines = query.ToArray();

Event Handlers

Event Handlers start out as null until someone attaches the first delegate to them.
If you use them before that, they go boom.

public class SparkPlug
{
    public void MakeSpark()
    {
        OnSparkMade(EventArgs.Empty);
    }

    public event EventHandler SparkMade;

    protected virtual void OnSparkMade(EventArgs e)
    {
        SparkMade(this, e); // boom
    }
}

static void Main()
{
    var sp = new SparkPlug();
    sp.MakeSpark(); // boom
}

Always test your event handlers before trying to execute their delegates.

protected virtual void OnSparkMade(EventArgs e)
{
    if (SparkMade != null)
    {
        SparkMade(this, e);
    }
}

Summary

Check for nulls all the time and you’ll be fine.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

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