I originally posted this post on my blog a couple of months ago. It's part of a series called "Goodbye, NullReferenceException."
This exception doesn't need an introduction. I bet you already have found the exception message: "Object reference not set to an instance of an object." Let's see when NullReferenceException is thrown and a strategy to fix it.
NullReferenceException is thrown when we access a property or method of an uninitialized variable of a reference type. To prevent this exception, check for null values before accessing the members of an object.
0. A simple example
Let's write an example that throws NullReferenceException,
var movie = FindMovie();
Console.Write(movie.Name);
// ^^^^^
// System.NullReferenceException: 'Object reference not set to an instance of an object.'
//
// movie was null.
Console.ReadKey();
static Movie FindMovie()
{
// Imagine this is a database call that might
// or might not return a movie
return null;
// ^^^^
}
record Movie(string Name, int ReleaseYear, float Rating);
Notice we returned null
from FindMovie()
. That caused the NullReferenceException. But, it could be a method that accessed a database and didn't find anything or an API controller method that didn't receive a required input parameter.
In our last example, we got a NullReferenceException when we returned null
from a method. But, we could also find this exception when we try to loop through a null
list or array, for example.
1. Don't catch the NullReferenceException
To fix the NullReferenceException, we might be tempted to write a try/catch
block around the code that throws it. But, let's not catch the NullReferenceException.
Let me say that again: don't throw or catch NullReferenceException.
By any means, please, let's not write something like this,
try
{
AMethodThatMightThrowNullReferenceException();
}
catch (NullReferenceException)
{
// ...
// Beep, beep, boop
// Doing something with the exception here
}
A NullReferenceException is a symptom of an unhandled and unexpected scenario in our code, and catching it won't handle that. A NullReferenceException is a developer's mistake. It's our fault!
2. Check for null
The solution for the NullReferenceException is to check for nulls and defense against them.
Let's fix our previous example by adding a null check or guard. Like this,
var movie = FindMovie();
if (movie != null)
// ^^^^^
{
// We're safe here...
//
// No more System.NullReferenceException
// at least due to a movie being null
Console.Write(movie.Name);
}
Console.ReadKey();
static Movie FindMovie()
{
// Imagine this is a database call that might
// or might not return a movie
return null;
// ^^^^
}
record Movie(string Name, int ReleaseYear, float Rating);
Notice we checked if the movie
variable wasn't null
. As simple as that!
Alternatives to check for null
The lack of options isn't an excuse to not check for null
. Since some recent C# versions, and thanks to pattern matching, we have a couple of new ways to check for null
. We can use any of these:
-
if (movie != null) { //... }
, -
if (movie is not null) { //... }
, -
if (movie is { }) { //... }
, and, if (movie is object) { //... }
Some of those don't look like C# anymore. I know! I still prefer the old if (movie != null) ...
. By the way, which one do you prefer?
3. Defense against null
If the solution to NullReferenceException were to simply check for null
, that wouldn't be the Billion-Dollar mistake. And I wouldn't be writing this post.
The thing is knowing when a reference might be null
or not and, therefore, when we should check for it. That's when we should protect ourselves against null
.
To protect against null
, inside our methods, let's check our input parameters and throw a more detailed exception. C# has an exception for missing parameters: ArgumentNullException.
The ArgumentNullException stack trace contains the name of the parameter that was null
. That will help us to better troubleshoot our code. Often, the NullReferenceException stack trace doesn't include what was null
in the first place. Arrrggg!
Let's check our input parameters,
public void DoSomething(Movie movie)
{
// Since C# 10, we can write:
ArgumentNullException.ThrowIfNull(movie);
// or in previous versions:
//if (movie == null)
//{
// throw new ArgumentNullException(nameof(movie))
//}
// Beep, beep, boop
// Doing something here...
}
Notice that instead of waiting for NullReferenceException, we proactively prevented it by checking for a required parameter and throwing a controlled ArgumentNullException.
Voilà! That's the NullReferenceException and how to fix it by checking for null
. Remember, we shouldn't catch this exception but prevent and prepare for it.
We only covered one technique to prevent this exception. But C# has introduced new operators and features to flag and handle null
in our code. Even, Functional Languages, like F# and Haskell, use a different approach to prevent null
in the first place.
If you want to read more C# content, check my C# Definitive Guide and my Unit Testing 101 series. Sure, unit tests help us to prevent NullReferenceException too.
Hey! I'm Cesar, a software engineer and lifelong learner. If you want to support my work, check my courses on Educative. I have precisely one course about preventing NullReferenceException where we cover more techniques like the ones in this post.
Happy coding!
Top comments (0)