How to Stop NullReferenceExceptions in .NET: Implementing Nullable Reference Types
August 10, 2021
This article gives you a toolset for stopping NullReferenceExceptions in .NET code. The article centers around Nullable Reference Types (NRT), a feature that Microsoft added in C# 8. This article mentions five additional tools to ensure that users will never encounter the exception and explains how to implement them in your code.
Use non-nullable variables (Reference and value types): flag variables that should never be nullNull object pattern: inject default implementations with null behavior instead of null referencesTreat NRT warnings as errors: enforce the NRT rules to ensure that variables cannot enter a null/not-null state at the wrong time. Treat NRT warnings as errors so code will not compile if it breaks the NRT rules.Immutability: reduce the risk of NullReferenceException by only setting the reference onceArgumentNullException: An oldy but a goody. Stop code execution early in cases where the consuming code does not treat NRT warnings as errors.Unit testing: pass nulls into your code to make sure the appropriate result occurs. Mutation testing can help you achieve a higher level of certainty in your tests.
Note: This article talks about libraries and consumers of those libraries. This might sound like it's about open-source libraries, and it is, but it's also about maintaining libraries in your team. If you publish libraries, someone will be consuming them, and that might even be you.
Nullable Reference Types
I recommend reading the official NRT documentation before or after reading this post. This article will refer to some terminology in that documentation which is important to understand.
Reference types (classes, delegates, interfaces) are nullable by their nature. So, why is there suddenly a feature in the language that makes it sound as though they are suddenly nullable? The answer is partly historical. Value types (primary data types and structs) are not inherently nullable. C# added the nullable values types feature and added a nullable ? shortcut in C# 7. The NRT feature follows on from this. It extends the concept so that types suffixed with ? are meant to allow null. The corollary of this is that when we turn NRT on (nullable aware context), types without the? flip from being inherently nullable to not nullable. The syntax also brings C# in line with several other modern languages like Dart.
When turned on, variables are in nullable aware context. You can turn nullable aware context on project by project or file by file. You need to turn it on file by file in the older csproj formats (pre SDK style). For example, you cannot turn it on at the project level for UWP or Android. Variables declared where nullable aware context is off are considered nullable oblivious.
If you leave this feature half-implemented, it could be confusing for people consuming the library. The IDE quick info bubbles may not identify between nullable aware and nullable oblivious variables. The consumer may not know if they allow null or not, and it's not easy for them to tell the difference between these and variables that are nullable oblivious. You might choose to convert entire projects for this reason or not to implement NRT on older projects.
Note: NRT support in IDEs is getting better, and IDEs will likely distinguish between nullable aware and nullable oblivious variables in the quick info in the future.
Turn on NRT (Nullable Aware Context)
There are a few different strategies for turning on NRT. I recommend doing it all at once and at the project level if you can. As mentioned, doing it for half a library could confuse the consumer. This is the Microsoft documentation on upgrading to NRT. Open up the csproj file and add these lines:
You will see lots of warnings. The existing variables where the reference type does not have a ? suffix will become not nullable. This flips the meaning of the existing code. Any reference type variables that were nullable change to not nullable. If you want to turn on nullable aware context at the file level, add this to the top of the file.
Note: you can also leave the language version at 8.
Turn on Treat Warnings as Errors
Warnings are not enough. You need to treat warnings as errors. Warnings are too easy to ignore, so you need to tell the compiler to stop compilation when you violate an NRT constraint. If you don't, you won't get the most s...
You will be working in a large US-oriented company that puts as a priority: security, performance, and stability. The candidate will work on pushing a huge number of changes (several thousand per sec) to several thousand clients in a near real-time manner.
Our customer is an American company that develops software for businesses to help manage their networks, systems, and information technology infrastructure. The company provides purpose-built products for IT professionals, MSPs, and DevOps pros.
We are looking for a Junior .Net developer for being involved in to further development of the B2B platform for IT companies. You'll work on mostly back-end tasks closely with a Senior level developer.
The ideal candidate will have released multiple Xamarin apps commercially and will have a proven track record working as part of a cross functional scrum team. We are seeking proactive, technology focused individuals with best in class development principles. On this team, coding is only part of what we do. Our real focus is on delivery, with backend, frontend and QA working closely together to create, deploy and test solutions. Our solutions will be deployed to a variety of complex environments and used by thousands of hospital patients and staff worldwide. Expect a rewarding and challenging experience.