Throwing null argument exceptions

December 24th 2021 C# .NET

NullReferenceException is probably one of the most common exceptions in .NET. It is thrown whenever you try to access a member of a reference type that is currently set to the value null. With the nullable reference types introduced in C# 8, the compiler can now warn you if you try to do this, so you can add a null check to prevent the exception from being thrown. You have to explicitly enable this feature if you want to use it. But since .NET 6 it is already enabled by default for every newly created project.

If you declare a reference-typed parameter to be non-nullable, the compiler will issue a warning if it is passed a value that can be null. If you choose to strictly fix these warnings in your project (or even treat them as errors), you can largely eliminate null checks for method and constructor parameters. This way you can get rid of a lot of plumbing code and also numerous tests if you are thorough in your test coverage.

However, you should not let nullable reference types lull you into a false sense of security. If your code is called by code that is not completely under your control (for example, if you create a public class library), you still need to do the null checks to be safe, because the consuming code might have nullable reference types disabled, or the developers might decide to ignore the warnings even though they have nullable reference types enabled.

Null checking code is simple, but very repetitive. Traditionally, it consists of a throw statement inside an if block:

if (paramName == null)
{
    throw new ArgumentNullException(nameof(paramName));
}

If you start copying this block of code (when there are multiple parameters), it is also very error-prone: you might forget to update the parameter name passed to the exception constructor to match the parameter you are null checking.

With the introduction of the null coalesing operator in C# 8 and the throw exception in C# 7, you can reduce the above code to a single expression:

this.paramName = paramName ?? throw new ArgumentNullException(nameof(paramName));

This works especially well in constructors where you often assign parameter values to local private fields.

But even though this pattern reduces the amount of code, you still need to make sure that the parameter you check for null matches the parameter you pass to the exception constructor. In .NET 6, a new static method has been added to ArgumentNullException to help you do this:

ArgumentNullException.ThrowIfNull(paramName);

Since you only need to pass the parameter once, there is no risk of a mismatch between the parameter you want to check and the parameter name contained in the thrown exception. The correct name is passed automatically thanks to the CallerArgumentExpression attribute.

In C# 11, checking parameters for null could become even easier. There is a proposal for a parameter null checking feature, which will cause the code to check for null to be automatically generated by the compiler when you mark a parameter with the new double bang operator:

public static string MyMethod(string paramName!!)
{
    // ...
}

As always with new features, the actual syntax could change by the time C# 11 is released, or the feature might not make it into C# 11 at all.

You can download a complete example with all three currently available approaches to throwing ArgumentNullException from my GitHub repository.

Nullable reference types are a great feature to reduce the likelihood of an unhandled NullReferenceException in your code. However, you still need to null check the parameters in the public interface of your class libraries. There are several ways to do this. The simplest and most fool-proof one is the new ArgumentNullException.ThrowIfNull static method introduced in .NET 6.

Get notified when a new blog post is published (usually every Friday):

If you're looking for online one-on-one mentorship on a related topic, you can find me on Codementor.
If you need a team of experienced software engineers to help you with a project, contact us at Razum.
Copyright
Creative Commons License