Monday, January 5, 2009

Exceptions 101: NullReferenceException

So, I've decided to start a series on exceptions. We've all seen them, and we've all had to work with them, but if you're early in your development career, you may not know exactly what each one of these means, why you're getting them, and what to do about it. So, I've decided to create a series on exceptions. Each post in the series is going to detail a specific exception, why you're getting it and how to get it to stop. Today's exception is the NullReferenceException.



The NullReferenceException is thrown whenever you're trying to use an object (either a class, or a Nullable type) that is currently set to null. It's typical message is "Object reference not set to an instance of an object". It differs from the ArgumentNullException, which I'll talk about in my next post, in that a NullReferenceException is thrown at runtime whenever the instance of the object is used, whereas the ArgumentNullException is thrown whenever a required parameter in a method is passed in as null. Think of ArgumentNullException as the exception that's thrown to avoid getting a NullReferenceException later. You should never explicitly throw a NullReferenceException yourself. Throw an ArgumentNullException instead.

So under what conditions is the NullReferenceException thrown? Usually, it's thrown when the developer is trying to access a method or a property of an instance of a class that is null. The following example demonstrates a NullReferenceException:

using System;

 

class Program

{

    static void Main(string[] args)

    {

        Widget widget = new Widget();

        Console.WriteLine(widget.Value);

        Console.ReadLine();

    }

}

 

public class Widget

{

    public string _value;

 

    public string Value

    {

        get { return _value.ToUpper(); }

        set { _value = value; }

    }

}


In this example, I'm creating a Widget class, but I never initialized the private field _value in the Widget. Unfortunately, the getter for the property Value tries to convert the _value to an upper case version of itself. It does this by calling "_value.ToUpper()". Because _value is null, a NullReferenceException is thrown, because the method cannot be called on an object set to null.

In some situations, it's a little more unclear as to what is null. This usually happens when there's alot of code compacted to one line. For example, take the following reflection code.

Widget widget = null;

string textValue = typeof(Widget).GetProperty("Text").GetValue(widget, null).ToString();

Console.ReadLine();


Now, you may initially think that the exception is thrown because the instance of Widget, widget is set to null, but that's not actually the reason it's thrown in this situation. Here, the NullReferenceException is actually thrown by the call to "GetValue", because the return of GetProperty happens to be null.

There are two ways I usually debug this particular error. The goal here is to find the null instance, so that code can be written to ensure it's value is set or to avoid it completely when it is null.

Debugging method 1: Use the ValueTips.

This works well for the first example, and in the situation where the object that is null is a property or field. To debug here, simply hover your mouse over the fields or properties in the line that is throwing the error, and if the value is null, you then know which value needs to be set, and you can take steps to resolve the issue. It looks something like this:



Debugging method 2: Use the Watch Window.

If you've never used the watch window, you should. It allows you to post most bits of code into a window, and have that code evaluated immediately. When the null object is returned from a method, this is the typically the best way to debug a null reference. The second example above is a great candidate for debugging this way.

First, open the watch window. There are four different instances of watch windows in Visual Studio. You can open any of them either from the menu (Debug -> Windows -> Watch -> Watch 1 through 4), or using the keyboard shortcut (Ctrl-Alt-W, followed by a number between 1 and 4).

Next, paste a portion of the offending code into the right portion of the watch window. Split apart the offending code by the "dots" that separate them. So, for instance, in the example above, I would first type in "typeof(Widget)" and see if that returns null. If it does not, I would then check "typeof(Widget).GetProperty("Text")", if that still returns a value, then I would check the next section, "typeof(Widget).GetProperty("Text").GetValue(widget, null)", and so on and so forth.

I've done this with the code above, and have found that GetProperty is returning null (apparently the property "Text" doesn't exist on a Widget), so I conclude that when GetValue is called, it's called on an object that is set to null, and thus I receive my NullReferenceException.



Come back on Wednesday, when we'll discuss NullReferenceException's big brother, ArgumentNullException.