Logo

dev-resources.site

for different kinds of informations.

C# Null-Conditional (?.) & Null-Coalescing (??) Operators Explained

Published at
1/4/2025
Categories
csharp
dotnet
dotnetcore
tutorial
Author
ivankahl
Categories
4 categories in total
csharp
open
dotnet
open
dotnetcore
open
tutorial
open
Author
8 person written this
ivankahl
open
C# Null-Conditional (?.) & Null-Coalescing (??) Operators Explained

You've likely bumped into the pesky NullReferenceException if you've developed anything in C#. This exception usually happens when you try to access a member of a variable that contains a null reference, disrupting the flow of your application.

Fortunately, C# offers some handy tools to help you navigate these null reference issues: the null-conditional and null-coalescing operators. These operators provide ways to handle potential null values gracefully while keeping your code clean and readable.

In this article, you will learn precisely how each operator works, when they should be used, and code samples demonstrating them in action.

What is the Null-Conditional Operator?

The null-conditional operator (?.) is a unary operator in C# that checks if a variable is null before accessing its members. If the variable is null, the expression short-circuits and evaluates to null, preventing a NullReferenceException from being thrown.

Short-circuiting means that if any part of a chained expression evaluates to null, the remaining parts are skipped, and the entire expression evaluates to null.

For example, if customer?.ContactDetails is null in the expression customer?.ContactDetails?.Email?.Work, then Email?.Work is never evaluated, and the expression returns null.

This operator is handy when retrieving values from deeply nested properties in an object. For example, suppose you have an object with nested properties. You can use the null-conditional operator to safely access properties deep within the object without explicitly checking for null at each level. This makes your code more concise and readable, especially when dealing with complex data structures.

// Without null-conditional operator
string? name = null;
if (customer != null && customer.Address != null)
{
    name = customer.Address.StreetName;
}

// With null-conditional operator
var? name = customer?.Address?.StreetName;
Enter fullscreen mode Exit fullscreen mode

In the example above, the second statement using the null-conditional operator achieves the same result as the first, but in a much more succinct way. If either customer or Address is null, the expression will evaluate to null, preventing a potential NullReferenceException.

A word of caution: while the null-conditional operator is quite helpful, you should only use it when it makes sense for a property to be null. Otherwise, you might run into some nasty surprises. For example, in the code snippet below, you already know customer is not null, so it's unnecessary to use the operator on that variable:

// Previously in the same code block:
if (customer is null) throw new CustomerNotFoundException();

// With null-conditional operator on everything (bad)
var streetNumber = customer?.Address?.Street?.Number;

// With null-conditional operator on nullable properties (good)
var streetNumber = customer.Address?.Street?.Number;
Enter fullscreen mode Exit fullscreen mode

While the example above might be harmless, there are cases where it can lead to strange bugs. For example, an expression might be evaluated as null, but it could be caused by a property in the expression chain you don't expect.

What is the Null-Coalescing Operator?

The null-coalescing operator is a binary operator that offers a concise method to manage null values. If the left operand if it is not null, it returns that; otherwise, it returns the right operand.

The syntax looks like this:

result = value1 ?? value2;
Enter fullscreen mode Exit fullscreen mode

In this case, if value1 is not null, the result will be assigned the value of value1. However, if value1 is null, the result will be assigned the value of value2.

This is useful when providing a default value for a nullable variable. For example, you might want to display a default value if a customer's address is a null string:

var customerAddress = customer?.Address;
var displayAddress = customerAddress ?? "Unknown Address";
Enter fullscreen mode Exit fullscreen mode

If the customer's address is specified, it'll be assigned to displayAddress. Otherwise, "Unknown Address" will be assigned to the variable.

You can even use the null-coalesce operator with the null-conditional operator shown above. For example, the above snippet could be combined into a single line like this:

var displayAddress = customer?.Address ?? "Unknown Address";
Enter fullscreen mode Exit fullscreen mode

Now, if the customer variable is null, the null-conditional operator will short-circuit the expression and return null. However, since we have a null-coalesce operator in the same line, "Unknown Address" is assigned to the displayAddress variable instead.

You can also use the null-coalescing operator in an assignment operation (??=). This is useful if you have an existing variable and only want to assign a value if the current value is null. The snippet below demonstrates this:

var customerName = customer?.Name;

// Without null-coalesce assignment operator
customerName = customerName ?? "No name provided";

// With null-coalesce assignment operator
customerName ??= "No name provided";
Enter fullscreen mode Exit fullscreen mode

Like the null-conditional operator, only use this operator when it makes sense. It's easy to fall into the habit of blindly assigning default values without considering whether they make sense. Sometimes a null is the best option:

// Here we assign "0" if a street number is not specified in
// an address... but does that make sense?
address.StreetNumber = request.Address.StreetNumber ?? "0";
Enter fullscreen mode Exit fullscreen mode

In the example above, a default value of "0" is assigned to StreetNumber if none is specified in the request object. However, this can be confusing. Imagine that the address is used for a delivery, and the driver mistakenly gets lost looking for a house with street number 0. In this case, it's probably better to leave it blank or null if it's not applicable.

Conclusion

You've undoubtedly bumped into NullReferenceExceptions, and they can be frustrating. Fortunately, C# provides operators specifically designed to streamline null handling and prevent those pesky exceptions from being thrown.

The null-conditional operator (?.) lets you safely access members of potentially null objects, while the null-coalescing operator (??) provides a concise way to supply default values when encountering nulls. Understanding and using these operators appropriately helps you write clear, robust C# code that gracefully handles null values.

dotnetcore Article's
30 articles in total
Favicon
.Net tarixi
Favicon
Oh bless me, Father, I have done something unholy: Installing .NET Core on Apple Silicon
Favicon
How to use Scoped service from Singleton Service in .Net Core
Favicon
How to add a Custom fields to Header in .NET Core Web API ?
Favicon
c#(.Net) - Basic Authentication WEB API
Favicon
CRUD operations on Arrays
Favicon
Working with interfaces
Favicon
Iterations
Favicon
Protfolio Website
Favicon
Dependency injection validation error in ASP.NET Core projects
Favicon
.Net Core and Kafka
Favicon
C# Null-Conditional (?.) & Null-Coalescing (??) Operators Explained
Favicon
Change a .Net Console application into an web application
Favicon
Efficient Bulk Operations with UkrGuru.Sql
Favicon
Improve Application Performance using β€œFire and Forget” in .NET Core
Favicon
API Versioning in .Net Core.
Favicon
Move objects from one folder to other in the same S3 Bucket using C# in AWS
Favicon
πŸŽ‰ We Made It: Trending in .NET on Dev.to! πŸš€
Favicon
.NET 9 Improvements for ASP.NET Core: Open API, Performance, and Tooling
Favicon
.Net Core Microservice Communication Using Kafka.
Favicon
Getting Started with .NET and Docker Tutorial
Favicon
Experimental attribute in C# is a powerful tool : Let's explore
Favicon
Implementing Chain of Responsibility Pattern in C# : Middleware's Design Pattern
Favicon
How to create a background email sender with outbox pattern integration
Favicon
The End of Microsoft's Monopoly on ASP.NET
Favicon
.NET Core MVC Project Structure : Implementing a Generic Service and Repository Pattern
Favicon
Did you know? How .NET Achieving Language Interoperability (C# + VB.NET = Same Application)
Favicon
These 10+ comparisons cover entire SQL concepts, Is it?
Favicon
NET 9 BinaryFormatter migration paths
Favicon
How to create a background email sender

Featured ones: