What Is the NullReferenceException?
Learn when a NullReferenceException is thrown.
Let’s start by learning when a NullReferenceException
is thrown.
Value and reference types
Generally speaking, C# has two kinds of types:
- Value types are all “primitive” types. These include integers, characters, and booleans.
- Reference types are more “complex” objects. These include strings and our custom objects.
When we declare a variable of a primitive type without an initial value, it gets assigned a default value. For example, integers are initialized to 0
and booleans to false
. But reference types are initialized to null
.
int anInt; // -> 0bool aBool; // -> falsestring aString; // -> null
With this context in mind, let’s see when the NullReferenceException
is thrown.
When is a NullReferenceException
thrown?
A NullReferenceException
is thrown when we access a property, field, or method of an uninitialized variable of a reference type.
Let’s write an example that throws a NullReferenceException
.
var movie = FindMovie();Console.WriteLine(movie.Name);static Movie FindMovie(){// Imagine this is a database call that might// or might not return a moviereturn null;// Often, in real life, it's more like this://var random = new Random();//return random.NextDouble() >= 0.5// ? new Movie("Titanic", 1997, 7.9f)// : null;}record Movie(string Name, int ReleaseYear, float Rating){// TODO: Add a IsAGoodMovie method here}
If we run our previous example without any changes, it throws a NullReferenceException
. We should get an error message like the one in the image below.
Notice we didn’t write a regular console application. We used top-level and global using statements to simplify our Main
class. We didn’t even write a class declaration, and we used a record to declare an immutable Movie
class from lines 18 to 21.
In the FindMovie()
method from lines 5 to 16, we return null
at line 9. We print the Name
property at line 3 of the returned value from line 1, which causes a NullReferenceException
. This would still be the case even if we had called any method in the Movie
class.
Let’s go back to the
Movie
class and add anIsAGoodMovie()
method to check if its rating is greater than five. Then, on line 3, use theIsAGoodMovie()
method instead of accessing theName
property. Do we still get aNullReferenceException
?
It might seem obvious or silly that we returned null
from a method. But it’s not that obvious in other scenarios. The FindMovie()
method could be a method that accessed a database and didn’t find any records, or it could be an API controller method that didn’t receive a required input parameter.
Similarly, we could get a NullReferenceException
from passing a null
as a parameter to a method that uses that parameter in its body.
Let’s go back to the previous example, and below the
FindMovie()
method, add a staticPrintMovie()
method that receives a movie and prints out its name. Then, on line 3, let’s use this new method, passing the result ofFindMovie()
. Do we still get aNullReferenceException
?
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. Sure enough, that’s what try
/catch
blocks are for. But let’s not throw or catch the NullReferenceException
.
Let’s not write something like this:
try{AMethodThatMightThrowNullReferenceException();}catch (NullReferenceException){// ...// Do something with the exception here}
A NullReferenceException
is a symptom of an unhandled and unexpected scenario in our code. Catching it doesn’t handle that.
Rather than catching it, we should prevent it in the first place, instead.