Export (0) Print
Expand All

Troubleshooting Exceptions: System.NullReferenceException

A NullReferenceException occurs when you try to use a method or property of a reference type (C#, Visual Basic) whose value is null. For example, you may have tried to use an object without first using the new keyword (New in Visual Basic), or tried to use an object whose value was set to null (Nothing in Visual Basic).

Most of the examples in this article use one or both of these classes:

public class Automobile
{
    public EngineInfo Engine {get; set;}
}

public class EngineInfo
{
    public EngineInfo() { }

    public EngineInfo(string powerSrc, double engineSize)
    {
        Power = powerSrc;
        Size = engineSize;
    }

    public double Size { get; set; }
    public string Power = null;
}
   

Back to topOther sections in this article

Any reference type variable can be null. Local variables, the properties of a class, method parameters, and method return values can all contain a null reference. Calling methods or properties of these variables when they are null causes a NullReferenceException. Specific cases:

A local variable or member field is declared but not initialized

A property or field is null

A method parameter is null

The return value of a method is null

An object in a collection or array is null

An object is not created because of a condition

An object passed by reference to a method is set to null

This simple error happens most frequently in Visual Basic code. Except in situations like declaring a variable to be passed as an out parameter, the C# compiler does not allow the use of a local reference variable unless it's initialized. The Visual Basic compiler generates a warning.

  • In the following C# code, the highlighted line generates this compiler error:

    Use of unassigned local variable 'engine'
  • In the Visual Basic code, the highlighted line generates compiler warning BC42104:

    Variable 'engine' is used before it has been assigned a value.
    
    A null reference exception could result at runtime.

    And the line does throw a NullReferenceException when it runs.

public void NullReferencFromUninitializedLocalVariable()
{
    EngineInfo engine;
    Console.WriteLine(engine.ToString());
}

Back to topEntries in this section

Back to topSections in this article

The fields and properties of a class are automatically initialized to their default value when the class is created. The default value of a reference type is null (Nothing in Visual Basic) Calling member methods on a field or property of a parent class when the field or property value is null causes a NullReferenceException.

In this example, the highlighted line throws a NullReferenceException because the Engine property of car is auto-initialized to null.

public void NullReferenceFromProperty()
{
    var car = new Automobile();

    Console.WriteLine(car.Engine.ToString());
}

Back to topEntries in this section

Back to topSections in this article

A method parameter that is a reference type can be null (Nothing in Visual Basic). Calling member methods or properties on a parameter value that is null causes a NullReferenceException.

In this example, the highlighted line throws a NullReferenceException because BadEngineInfoPassedToMethod calls NullReferenceFromMethodParameter with a parameter that is null.

public void BadEngineInfoPassedToMethod()
{
    EngineInfo eng = null;
    NullReferenceFromMethodParameter(eng);
}

public void NullReferenceFromMethodParameter(EngineInfo engine)
{
    Console.WriteLine(engine.ToString());
}

Back to topEntries in this section

Back to topSections in this article

A method that returns a reference type can return null (Nothing in Visual Basic). Calling methods or properties of the returned reference type causes a NullReferenceException when the reference is null.

In this example, the highlighted line throws a NullReferenceException because the call to BadGetEngineInfo returns a null reference in the NullReferenceFromMethodParameter method.

public EngineInfo BadGetEngineInfo()
{
    EngineInfo engine = null;
    return engine;
}

public void NullReferenceFromMethodReturnValue()
{
    var engine = BadGetEngineInfo();
    Console.WriteLine(engine.ToString());
}

Back to topEntries in this section

Back to topSections in this article

A list or array of reference types can contain an item that is null. Calling methods or properties of a list item that is null causes a NullReferenceException.

In this example, the highlighted line in NullReferenceFromListItem() throws a NullReferenceException because the call to BadGetCarList returns an item that is null.

public Automobile[] BadGetCarList()
{
    var autos = new Automobile[10];
    for (int i = 0; i autos.Length; i++)
    {
        if (i != 6)
        {
            autos[i] = new Automobile();
        }
    }
    return autos;
}

public void NullReferenceFromListItem()
{
    var cars = BadGetCarList();
    foreach (Automobile car in cars)
    {
        Console.WriteLine(car.ToString());
    }
}

Back to topEntries in this section

Back to topSections in this article

If a reference type is initialized in a conditional block, the object is not created when the condition is false.

In this example the highlighted line in NullReferenceFromConditionalCreation throws a NullReferenceException because it initializes the engine variable only if the DetermineTheCondition() method returns true.

 public bool DetermineTheCondition()
{
    return false;
}

public void NullReferenceFromConditionalCreation()
{
    EngineInfo engine = null;
    var condition = DetermineTheCondition();
    if (condition)
    {
        engine = new EngineInfo();
        engine.Power = "Diesel";
        engine.Size = 2.4;
    }
    Console.WriteLine(engine.Size);
}

Back to topEntries in this section

Back to topSections in this article

When an object is passed as a parameter to a method by value (without use of the ref or out keyword in C# or the ByRef keyword in Visual Basic), the method can't change the memory location of the parameter—what the parameter points to—but it can change the properties of the object.

In this example, the NullPropertyReferenceFromPassToMethod method creates an Automobile object and initializes the Engine property. It then calls BadSwapCarEngine, passing the new object as the parameter. BadSwapCarEngine sets the Engine property to null, which causes the highlighted line in NullPropertyReferenceFromPassToMethod to throw a NullReferenceException.

public void BadSwapCarEngine(Automobile car)
{
    car.Engine = null;
}

public void (Automobile car)
{
    car.Engine = new EngineInfo("GAS", 1.5);
    BadSwapCarEngine(car);
    Console.WriteLine(car.Engine.ToString());
}

Back to topEntries in this section

Back to topSections in this article

When you pass a reference type as a parameter to a method by reference (using the ref or out keyword in C# or the ByRef keyword in Visual Basic), you can change the memory location that the parameter points to.

If you pass a reference type by reference to a method, the method can set the referenced type to null (Nothing in Visual Basic).

In this example, the highlighted line in NullReferenceFromPassToMethodByRef throws a NullReferenceException because the call to the BadEngineSwapByRef method sets the stockEngine variable to null.

public void BadEngineSwapByRef(ref EngineInfo engine)
{
    engine = null;
}

public void NullReferenceFromPassToMethodByRef()
{
    var stockEngine = new EngineInfo();
    stockEngine.Power = "Gas";
    stockEngine.Size = 7.0;
    BadSwapEngineByRef(ref stockEngine);
    Console.WriteLine(stockEngine.ToString());
}

Back to topEntries in this section

Back to topSections in this article

Use data tips, the Locals window, and watch windows to see variables values

Walk the call stack to find where a reference variable is not initialized or set to null

Set conditional breakpoints to stop debugging when an object is null (Nothing in Visual Basic)

  • Rest the pointer on the variable name to see its value in a data tip. If the variable references an object or a collection, you can expand the data type to examine its properties or elements.

  • Open the Locals window to examine the variables that are active in the current context.

  • Use a watch window to focus on how a variable changes as you step through the code.

Back to top Entries in this section

Back to top Sections in this article

The Visual Studio Call Stack window displays a list of the names of methods that have not completed when the debugger stops at an exception or breakpoint. You can select a name in the Call Stack window and choose Switch to frame to change the execution context to the method and examine its variables.

Back to top Entries in this section

Back to top Sections in this article

You can set a conditional breakpoint to break when a variable is null. Conditional breakpoints can be helpful when the null reference does not occur often—for example, when an item in a collection is null only intermittently. Another advantage of conditional breakpoints is that they enable you to debug an issue before you commit to a particular handling routine.

Back to top Entries in this section

Back to top Sections in this article

Use Debug.Assert to confirm an invariant

Fully initialize reference types

An invariant is a condition that you are sure is true. A Debug.Assert (System.Diagnostics) statement is called only from debug builds of your apps and is not called from release code. If the invariant condition is not true, the debugger breaks at the Assert statement and displays a dialog box. Debug.Assert provides a check that the condition has not changed while you are developing the app. An assertion also documents for others who read your code that the condition must always be true.

For example, the MakeEngineFaster method assumes that its engine parameter will never be null because its only caller method (TheOnlyCallerOfMakeEngineFaster) is known to fully initialize the EngineInfo. The assert in MakeEngineFaster documents the assumption and provides a check that the assumption is true.

If someone adds a new caller method (BadNewCallerOfMakeEngineFaster) that does not initialize the parameter, the assert is triggered.

private void TheOnlyCallerOfMakeEngineFaster()
{
    var engine = new EngineInfo();
    engine.Power = "GAS";
    engine.Size = 1.5;
    MakeEngineFaster(engine);
}

private void MakeEngineFaster(EngineInfo engine)
{
    System.Diagnostics.Debug.Assert(engine != null, "Assert: engine != null");
    engine.Size *= 2;
    Console.WriteLine("The engine is twice as fast");
}

private void BadNewCallerOfMakeEngineFaster()
{
    EngineInfo engine = null;
    MakeEngineFaster(engine);
}

Back to topEntries in this section

Back to topSections in this article

To avoid many NullReferenceExceptions, fully initialize reference types as close to their creation as possible.

Add full initialization to your own classes

If you control the class that throws a NullReferenceException, consider fully initializing the object in the type’s constructor. For example, here’s a revised version of the example classes that guarantees full initialization:

public class Automobile
{
    public EngineInfo Engine { get; set; }

    public Automobile() 
    { 
        this.Engine = new EngineInfo(); 
    }

    public Automobile(string powerSrc, double engineSize)
    {
        this.Engine = new EngineInfo(powerSrc, engineSize);
    }
}


public class EngineInfo
{
    public double Size {get; set;}
    public string Power {get; set;}

    public EngineInfo() 
    { 
        // the base engine 
        this.Power = "GAS"this.Size = 1.5; 
    }

    public EngineInfo(string powerSrc, double engineSize)
    {
        this.Power = powerSrc;
        this.Size = engineSize;
    }
}
NoteNote

Use lazy initialization for large or infrequently used properties

To reduce the memory footprint of your class and to increase its performance, consider using lazy initialization of reference-type properties. See Lazy Initialization.

Check for null (Nothing in Visual Basic) before using a reference type

Use try – catch – finally (Try – Catch – Finally in Visual Basic) to handle the exception

It's better to avoid a NullReferenceException than to handle it after it occurs. Handling an exception can make your code harder to maintain and understand, and can sometimes introduce other bugs. A NullReferenceException is often a non-recoverable error. In these cases, letting the exception stop the app might be the best alternative.

However, there are many situations where handling the error can be useful:

  • Your app can ignore objects that are null. For example, if your app retrieves and processes records in a database, you might be able to ignore some number of bad records that result in null objects. Recording the bad data in a log file or in the application UI might be all you have to do.

  • You can recover from the exception. For example, a call to a web service that returns a reference type might return null if the connection is lost or the connection times out. You can attempt to reestablish the connection and try the call again.

  • You can restore the state of your app to a valid state. For example, you might be performing a multi-step task that requires you to save information to a data store before you call a method that throws a NullReferenceException. If the uninitialized object would corrupt the data record, you can remove the previous data before you close the app.

  • You want to report the exception. For example, if the error was caused by a mistake from the user of your app, you can generate a message to help him supply the correct information. You can also log information about the error to help you fix the problem. Some frameworks, like ASP.NET, have a high-level exception handler that captures all errors to that the app never crashes; in that case, logging the exception might be the only way you can know that it occurs.

Here are two ways to handle NullReferenceException in release code.

Using an explicit test for null before you use an object avoids the performance penalty of try-catch-finally constructs. However, you still have to determine and implement what to do in response to the uninitialized object.

In this example, the CheckForNullReferenceFromMethodReturnValue tests the return value of the BadGetEngineInfo method. If the object is not null, it is used; otherwise, the method reports the error.

public EngineInfo BadGetEngineInfo()
{
    EngineInfo engine = null;
    return engine;
}

public void CheckForNullReferenceFromMethodReturnValue()
{
    var engine = BadGetEngineInfo();
    if(engine != null)
    {
        // modify the info
        engine.Power = "DIESEL";
        engine.Size = 2.4;
    }
    else
    {
        // report the error
        Console.WriteLine("BadGetEngine returned null")
    }
}

Back to topEntries in this section

Back to topSections in this article

Using the built-in exception handling constructs (try, catch, finally in C#, Try, Catch, Finally in Visual Basic) offers more options for dealing with NullReferenceExceptions than checking whether an object is not null.

In this example, CatchNullReferenceFromMethodCall uses two asserts to confirm the assumption that its parameter contains a complete automobile, including an engine. In the try block, the highlighted line throws a NullReferenceException because the call to RarelyBadEngineSwap can destroy the car's Engine property. The catch block captures the exception, writes the exception information to a file, and reports the error to the user. In the finally block, the method insures that the state of the car is no worse than when the method began.

public void RarelyBadSwapCarEngine(Automobile car)
{
    if ((new Random()).Next() == 42)
    {
        car.Engine = null;
    }
    else
    {
        car.Engine = new EngineInfo("DIESEL", 2.4);
    }
}

public void CatchNullReferenceFromMethodCall(Automobile car)
{
    System.Diagnostics.Debug.Assert(car != null, "Assert: car != null");
    System.Diagnostics.Debug.Assert(car.Engine != null, "Assert: car.Engine != null");

    // save current engine properties in case they're needed
    var enginePowerBefore = car.Engine.Power;
    var engineSizeBefore = car.Engine.Size;

    try
    {
        RarelyBadSwapCarEngine(car);
        var msg = "Swap succeeded. New engine power source: {0} size {1}";
        Console.WriteLine(msg, car.Engine.Power, car.Engine.Size);
    }
    catch(NullReferenceException nullRefEx)
    {
        // write exception info to log file
        LogException(nullRefEx);
        // notify the user
        Console.WriteLine("Engine swap failed. Please call your customer rep.");
    }
    finally
    {
        if(car.Engine == null)
        {
            car.Engine = new EngineInfo(enginePowerBefore, engineSizeBefore);
        }
    }
}

Back to topEntries in this section

Back to topSections in this article

Show:
© 2014 Microsoft