Prevent Frustrating Null Related Exceptions Using Operators Designed to Handle Null Situations
In programming, null reference and null argument exceptions can be costly and cause a program to unexpectedly crash. However, the functionality would have otherwise worked if a default value or specific null handing had been provided.
C# has several ways to handle situations when a variable could be null. The null coalescing and null conditional operators allow the programmer to prevent null reference and argument null exceptions. Programmers can use these operators to specifically provide code that addresses the null case without cluttering the code with if statements.
The null coalescing operator, ??, is useful when handling variables that could be null. The left-hand side is evaluated and if it is not null, the left-hand side is returned, otherwise the right-hand side is returned.
For example, null coalescing can be used if a default value can be used when a null is provided. In the code below, a list of integer values is provided by a different class. It is possible for the GetValues function to return null if no values are available. The example function below will default the function return value to an empty list if no values are returned.
C# 8 adds the null coalescing assignment operator, ??=. With this operator, if the left-hand side is null, the right-hand side is assigned to the left-hand side. This is particularly useful when lazy loading objects, such as in a singleton pattern.
The example below shows a WaterSensors singleton class that lazy loads the instance object.
With C# 8, the instance function can be rewritten to use the null coalescing assignment operator, shown below (also using expression-bodied member syntax).
The null conditional operators, ?. and?, check if the object is null before applying the operation to its operand. If the left-hand side is null then it will return null for the statement.
For example, the null conditional operator will check if an object is null before calling a member function, property, or indexing into an array/collection. Consider a function that returns the count of even numbers in a list of integers.
In the code above, if the numbers list is null, it will throw an argument null exception. To prevent the argument null exception, the ?. operator can be used, shown below.
However, this code won’t compile because now it is possible for the entire line to evaluate to null if numbers are null and the int return value cannot be null. It is easy to fix this by using a null coalescing operator, shown below. In this case, if numbers is null the function will return a count of zero.
Null conditional also provides thread-safe execution when invoking a delegate. Programmers no longer need to assign the delegate to a local “handler” variable and check for null. The code below raises an event when a value is changed.
The OnValueChanged function can be simplified to the following code using the null conditional operator and it is still thread-safe.
Using null coalescing and null conditional operators is a great way to write clean and readable C# code. Implementing these operators prevents unnecessary null-related exceptions, like null reference and argument null exceptions.
C# 8 goes a step further and provides programmers with the option to specify which, if any, objects can be null with nullable reference types. Learn more about this in part 2 of Null Values in C#.