Stackify is now BMC. Read theBlog

What Is NullReferenceException? Object reference not set to an instance of an object.

By: mwatson
  |  September 29, 2023
What Is NullReferenceException? Object reference not set to an instance of an object.

Description: What Is NullReferenceException? Object reference not set to an instance of an object

“Object Reference Not Set to an instance of an object.” Cast the first stone for those who never struggled with this error message as a beginner C# / .NET programmer.

This infamous and dreaded error message happens when you get a NullReferenceException. This exception throws when you attempt to access a member. For instance, a method or a property on a variable that currently holds a null reference.

But what does null reference exactly mean? What exactly are references? And how can you stop the NullReferenceException occurring in your code? Let’s take a look.

We’ll start with fundamentals by briefly explaining what references are in C# / .NET. After that, you’ll learn what null references are.

Following our exploration of theoretical definitions, we will dig into a more hands-on approach. This will guide you on preventing the occurrence of the NullReferenceException in real-world applications.

What Are References?

We already know that a null reference causes the NullReferenceException. But in what way does it differ from a non-null reference?

In .NET, data types are categorized into two groups: value types and reference types. A value type variable stores the actual value, whereas a reference type variable holds a reference pointing to the location of the object in memory. This reference functions like a link or shortcut, providing access to a web page or file on your computer, helping you understand where the object resides.

Types such as int (and the other numerical primitive types), DateTime, and boolean are value types. That is, structs are value types. Classes are reference types.

So, a reference is what a variable of a reference type contains. Variables can become empty, which we call a null reference: a reference that doesn’t point to any object. When you try calling a method or another member on an empty variable, you get the NullReferenceException.

Understanding the NullReferenceException

Null reference errors are responsible for a good percentage of all application bugs. Null references are often problems that arise from the lack of additional logic to verify if objects possess valid values before utilizing those objects. Here are some ways a NullReferenceException can occur:

Invoking a Method on a Null Object Reference

If the variable “text”  is passed in as null to the function MyMyethod, the following code will throw a NullReferenceException. You cannot invoke the ToUpper() method on a string that is null.

public void MyMethod(string text)

{
 //Throws exception if text == null
 if (text.ToUpper() == “Hello World”)
 {
      //do something
 }
}

You can also have null reference exceptions because any object type is null, not just string. For example, the code below never modifies the SqlCommand object.

Not running a SQL query would be a serious problem for your application. A null string might be something you just ignore and move on. Sometimes, especially with SqlCommand, it indicates a serious issue.

SqlCommand command = null;
//Exception! Object reference is not set to an instance of an object
command.ExecuteNonQuery();

Simple Examples of Null Values Causing Problems

Some of the most common causes are settings, database calls or API-type calls not returning expected values. For example, you add a new field to your database and don’t populate default values for every record. The code failed to account for the fact that it queries random records, and the new field is null. KA-BOOM: Object reference not set to an instance of an object.

How to Avoid the NullReferenceException?

Use the Null Conditional Operator to Avoid NullReferenceExceptions

The null conditional operator is one of the best additions to C#. Instead of many “variable != null” checks, use “?” to return null instead of throwing an exception. This will make more sense with some examples below:

text?.ToUpper(); //from previous example, would return null
int? length = customerList?.Length; // null if customerList is null  
Customer first = customerList?[0]; // null if customerList is null 
int? count = customerList?[0]?.Orders?.Count(); // null if customerList, the first customer, or Orders is null

Use Null Coalescing to Avoid NullReferenceExceptions

Another great feature is null coalescing, or the “??” operator. It works great for providing a default value for a null variable and works with all nullable data types.

The following code throws an exception if we don’t use null coalescing. Adding “?? new List<string>()” prevents the “Object reference not set to an instance of an object” exception.

List<string> values = null;
foreach (var value in values ?? new List<string>())
{
    Console.WriteLine(value);
} 
 

Avoiding NullReferenceException With C# 8.0’s Nullable Types

Bugs with null references happen because, in C#, any reference type object can be null at any time. What if, as a developer, you could ensure that a specific string will never be null?

What if the compiler prevented the accidental assignment of null to a variable? Sounds amazing? Good news, then: this is a real feature of the eighth version of C# called, obviously, nullable types.

The feature works ingeniously and powerfully by redefining the reference types as non-nullable by default—as many argue they should’ve been from the start.

To understand better, take a look at the following example:

static int Add(string numbers)

static int Add(string numbers)
{
return numbers.Split(“,”).Select(int.Parse).Sum();
}

In the pre-8.0 version of C#, the code above is dangerous. The numbers variable could be null, which would cause a NullReferenceException when trying to use the Split method.

The feature of nullable reference types in C# 8.0 would ensure your safety. The variable could never be null, and the call to the Split method would never throw an exception. Any attempt to pass null to the Add method would result in a compilation error.

But what if you wished to permit null values in numbers? In that case, you’d just have to add a question mark after the type’s name:

static int Add(string? numbers)
{
            return numbers.Split(“,”).Select(int.Parse).Sum();
}

There has been a significant shift, and Figures can now be null too. The compiler will warn you to check the variable’s value. You can even make the warning a compiler error for extra safety.

Description: Code Snippet

The compiler indicates that “numbers” has the potential to be null. Possible solutions include:

  • Using an if-statement to ensure the variable has a valid reference
  • Using the already-mentioned null-coalescing operator when calling the Split method
  • Making the “numbers” variable non-nullable again by removing the question mark

Keep in mind that this feature is opt-in. It comes disabled by default, and you must activate it in your project’s configuration. The reason is that shipping the feature already enabled would cause breaking changes in most code bases.

C# 10: Non-Nullable Reference Types (NRT) Enhancements

C# 10 builds upon the nullable reference types feature introduced in C# 8.0, making it more robust and providing better tools for preventing null reference exceptions.

  • Global Usings for Nullable Attributes: C# 10 introduced global usings for nullable attributes, allowing you to import attributes like [NotNull] and [MaybeNull] globally in your project to make annotating types easier.
  • Improved Warnings and Analysis: C# 10 improves warnings related to nullable reference types, making it easier to identify potential null reference issues at compile-time.

Example:

// Enable nullable annotations globally for the entire project
global using System;
global using System.Diagnostics.CodeAnalysis; // Import the nullable attributes globally

#nullable enable // Enable nullable reference types

public class Example
{
    public string? GetName()
    {
        return "John"; // This method can return null (string?)
    }

    public void PrintName()
    {
        string? name = GetName(); // Nullable reference type
        if (name is not null)
        {
            Console.WriteLine($"Name: {name}");
        }
        else
        {
            Console.WriteLine("Name is null");
        }
    }

    public void UseNotNullAttribute([NotNull] string value)
    {
        // This method expects a non-null value
        Console.WriteLine($"Value: {value}");
    }

    public void Demo()
    {
        string? name = GetName();
        UseNotNullAttribute(name); // Compiler will issue a warning
    }
}

In this example:

  1. We enable nullable reference types with #nullable enable globally for the entire project.
  2. We use the global using directive to import System.Diagnostics.CodeAnalysis, which contains the nullable attributes [NotNull] and [MaybeNull], globally for the project.
  3. The GetName() method returns a nullable string (string?), indicating that it can return null.
  4. In the UseNotNullAttribute method, we apply the [NotNull] attribute to the value parameter, indicating that it expects a non-null argument.
  5. In the Demo method, we call UseNotNullAttribute(name), which passes the nullable name variable as an argument. The compiler will issue a warning because we’re passing a nullable value to a method that expects a non-null argument, thanks to the global usings for nullable attributes.

Global usings for nullable attributes help you catch potential null reference issues at compile-time, improving code safety and readability. Please note that language features and syntax may have evolved since my last update, so it’s a good idea to consult the official C# documentation for the most up-to-date information on global usings and nullable attributes in the latest C# versions.

The Golden Rule of Programming

I’ve had a motto for several years that I consistently share with my team. I refer to it as the golden rule of coding. I think every new programmer needs a tattoo that says it.

“If it can be null, it will be null”

Adding extra logic and code can help prevent null reference errors by checking if objects are null before using them. Developers should always assume everything is invalid and be very defensive in their code.

Always pretend every database call is going to fail. Typically, each domain is likely to contain highly disorganized data. Good exception-handling best practices are critical.

What Are the Next Steps?

Null reference exceptions are common in .NET and most programming languages. Fortunately, we can all point fingers at Tony Hoare. He invented null references and even calls it the billion-dollar mistake.

What are the strategic measures we can implement to prevent this issue? One option is to adhere to my golden rule: if it can be null, it will be null!!

Nowadays, fortunately, we have the help of the compiler itself when fighting against the NullReferenceException. Turn on the “nullable reference types” feature in C# 8.0 to avoid null values if desired. The principle is: If it can’t be null, it’ll never be null. The compiler will forbid it!

Do you want to know more about C#, exceptions, and other related topics? If so, stay in tune with the Stackify blogs, since we’re always publishing posts on these topics and more.

Profiler & APM Tools Developers Can Trust

Before you push your code, you must improve the user experience and optimize the bottlenecks. To make this possible, make sure you leverage the power of the tools at your disposal.

For example – tools from Stackify by Netreo, like Prefix. Affectionately known as the Developer’s Sidekick, Prefix is a lightweight code profiler that validates the performance of your code while you write it. As a result, Prefix helps even the most experienced developers push better code to test and receive fewer support tickets. How, you ask?

Prefix captures detailed snapshots of web requests, enabling you to quickly identify and resolve hidden exceptions, slow queries, and other performance issues. Prefix natively supports web applications in .NET, Java, PHP, Node.js, Python or Ruby. And with the recent addition of OpenTelemetry data ingestion, Prefix now handles twice the programming languages, adding C++, Erlang/Elixir, Go, Javascript, Rust and Swift. And you can download Prefix for Free and try it today!

Maximize App Performance with Retrace APM

Once in production, DevOps can ensure ongoing app performance with Retrace, our full lifecycle APM solution. With more than 1,000 customers, Retrace helps software development teams monitor, troubleshoot and optimize the performance of their applications. Retrace provides real-time APM insights, enabling developers to quickly identify, diagnose and resolve errors, crashes, slow requests and more. For more on the features of Retrace, start your Free Trial today!

Improve Your Code with Retrace APM

Stackify's APM tools are used by thousands of .NET, Java, PHP, Node.js, Python, & Ruby developers all over the world.
Explore Retrace's product features to learn more.

Learn More

Want to contribute to the Stackify blog?

If you would like to be a guest contributor to the Stackify blog please reach out to [email protected]