Sometimes, during our projects, we might get a Null Reference Exception coming from a deep and forgotten part of our code.
In this article, we will understand why it happens, and explore a few ways to solve it.
Whenever you try to access an object or variable, which is not properly instantiated or initialized, you might get a Null Reference Exception.
Let's look at the example below. We have a class called People
, with a property called Name
, which type is a class. Although the property FullName
treats the error of getting its value before its being assigned, returning a default empty string, we don't have the same for Name
property within People
class.
try
{
var joel = new People();
var joelsName = joel.Name.FullName; //throws an Exception
}
catch (System.Exception exp)
{
System.Console.WriteLine(exp);
}
class People {
public Name Name { get; set; }
}
class Name {
public string FullName { get; set; } = String.Empty;
}
Running the code above results in the following:
constructor. Consider declaring the property as nullable. [..\dotnetlabs\NullReference\NullReference.csproj]
System.NullReferenceException: Object reference not set to an instance of an object.
at Program.<Main>$(String[] args) in
Note: I removed the path information once that is private. In your
case the location of your program would be shown instead.
Now that we understand why this error happens, it's time to solve it. I listed three solutions you can take in your code to avoid getting this Exception.
Solution 1: Declaring variables as being nullable
If you intend to use null in your logic, then you must declare the variables as nullable by adding a question mark at the end of the name.
try
{
var joel = new People();
var joelsName = joel.Name?.FullName; // we don't get NullReference Exception any more
}
catch (System.Exception exp)
{
System.Console.WriteLine(exp);
}
class People {
public Name? Name { get; set; }
}
class Name {
public string FullName { get; set; } = String.Empty;
}
Observe that I put the question mark in the property declaration and also when I invoke it to access the FullName
property.
The code above doesn't throw an Exception anymore, once the program understands now that a null value is expected from Name
property.
Solution 2: Treating the getter
Another option is to intercept when the program tries to read the Name property, so whenever the program tries to read the property it checks if it is null first, if so then returns a new instance of the object:
try
{
var joel = new People();
var joelsName = joel.Name.FullName; // we don't get NullReference Exception any more
}
catch (System.Exception exp)
{
System.Console.WriteLine(exp);
}
class People
{
private Name? _name;
public Name Name
{
get
{
if (_name is null)
{
return new Name();
}
return _name;
}
set
{
_name = value;
}
}
}
class Name
{
public string FullName { get; set; } = String.Empty;
}
Solution 3: Using constructors
A third option is to guarantee the properties and variable values using constructors. Whenever a constructor is defined, it forces you to instantiate the object. You should use the constructor logic to make sure none of your variables and properties are null.
try
{
var joel = new People("Joel Smith");
var joelsName = joel.Name.FullName;
Console.WriteLine(joelsName);
}
catch (System.Exception exp)
{
System.Console.WriteLine(exp);
}
class People
{
public Name Name { get; set; }
public People(string name)
{
Name = new Name(name);
}
}
class Name
{
public string FullName { get; set; } = String.Empty;
public Name(string name)
{
FullName = name;
}
}
Conclusion
In the majority of cases, you should avoid working with null values, as they might be a bad idea if not handled properly. However, there are a few cases in which we can use nulls to represent badly parsed data or a no value when querying some database. If so, you must treat them correctly to avoid your program breaking unexpectedly.