Null Coalescing vs Null Conditional in Clean Code

In this article, I will demonstrate Null Coalescing (??) and Null Conditional (?.). Dealing with null references is a common challenge in programming, but modern languages like C# offer elegant solutions. The null coalescing operator (??) and the null conditional operator (?.) are distinct yet complementary tools for writing clean and safe code. This article explores their functionality, provides examples, and guides you on their usage.

Null check

What is Null Coalescing (??)?

The null coalescing operator (??) provides a fallback value when a variable is null, serving as a concise alternative to traditional null-checking if statements.

Syntax

result = variable ?? fallbackValue;

How does Null Coalescing (??) work?

  • If variable is not null, its value is assigned to result.
  • If variable is null, the fallbackValue is assigned instead.
    string userName = null;
    string displayName = userName ?? "Guest User";
    Console.WriteLine(displayName); 
  • The null coalescing operator (??) simplifies null-checking logic.
  • In this example, displayName is guaranteed to have a value, even if userName is null.
  • This approach is more concise and readable compared to an equivalent if statement:

The traditional method to achieve this before the introduction of ??

string displayName;
if (userName != null)
{
    displayName = userName;
}
else
{
    displayName = "Guest";
}

When to use the null coalescing operator (??)

Default Values: Assign a default value when a variable is null.

Dictionary<string, string> userPreferences = new Dictionary<string, string>()
        {
            { "theme", "dark" },
            { "language", "en" }
        };
        
// Use ?? to provide a default value if the key doesn't exist
string theme = userPreferences.GetValueOrDefault("theme") ?? "light";
string fontSize = userPreferences.GetValueOrDefault("fontSize") ?? "medium";

Console.WriteLine($"Theme: {theme}");       // Output: Theme: dark 
Console.WriteLine($"Font Size: {fontSize}"); // Output: Font Size: medium

Output

  • Theme: dark   => requested value exists in the dictionary, so it will return the same value
  • Font Size: medium  => requested values do not exist, then it will return default values provided using the null coalescing operator (??)

Chained Fallbacks: Provide multiple fallback options.

string preferredName = null;
string alternateName = null;
        
// Use ?? to check both variables and provide a default value if both are null
string displayName = preferredName ?? alternateName ?? "Unknown Person";
Console.WriteLine(displayName);  // Output: Unknown Person

Output

"Unknown Person" because both variable assigned with null value.

  • The null coalescing operator can be chained to check multiple variables.
  • The operator will return the first non-null value from the chain.
  • If all variables are null, it will return the last fallback value. In this case, "Unknown".

The traditional method to achieve multiple null checks before the introduction of ??

string preferredName = null;
string alternateName = null;
        
// Traditional method using if statements
string displayName;
        
 if (preferredName != null)
 {
     displayName = preferredName;
}
 else if (alternateName != null)
  {
     displayName = alternateName;
  }
  else
  {
     displayName = "Unknown Person";
  }

Console.WriteLine(displayName);  // Output: Unknown Person

What is Null Conditional (?.)

The null conditional operator ?. allows safe navigation of objects and their properties, avoiding null reference exceptions. It short-circuits evaluation if the object or property being accessed is null.

Syntax

result = object?.Property;

How does Null Conditional (?.) work?

public class Person
{
    public int Id { get; set; }
    public string Name { get; set; }
    public Address Address { get; set; }
}

public class Address
{
    public int Id { get; set; }
    public string City { get; set; }
    public string PinCode { get; set; }
}
Person person = null;
        
 // Use the null conditional operator to safely access a property
 string name = person?.Name ?? "Unknown";
        
 Console.WriteLine(name);  // Output: Unknown

 string persionCity = person?.Address?.City ?? "Banglore"; // If person or Address object null then it will assign default city as Banglore

The null conditional operator (?.) is used to safely access the Name property of person. Since person is null, person?.Name will return null.

When to use Null Conditional (?.)

  • The null conditional operator (?.) allows you to safely access properties or methods of potentially null objects without throwing exceptions.
  • It can be chained to access multiple levels of properties, like person?.Address?.City.
  • It works well in scenarios where the object might be null and you want to avoid explicit null checks.

Comparing Null Coalescing (??) and Null Conditional (?.)

Null Coalescing (??)

  • Use it when you need to provide a fallback value if an expression evaluates to null.
  • It's commonly used in scenarios involving value assignment or default parameters.

Null Conditional (?.)

  • Use it when you need to safely access or call properties and methods on potentially null objects.
  • It's frequently used in deep object hierarchies or when dealing with nullable types.

Combining Both ?? and ?

Consider the example above with the Person class, which has an Address reference, and we want to use a combination of both ?? and ?. to check for null. Here's how we can implement it:

string userCity = person?.Address?.City ?? "Unknown City";
Console.WriteLine(userCity); // Output: Unknown City

Summary

In this article, we have examined how to handle null checks more efficiently by utilizing C#'s Null Coalescing (??) and Null Conditional (?.) operators. We discussed how these features can be applied to implement null checks in a cleaner, more readable manner, improving both the clarity and maintainability of the code. Additionally, we explored how to use these operators individually as well as how to combine them in a single statement to handle multiple null checks effectively, making the code more concise and eliminating the need for verbose null-checking logic.

Feel free to follow me here, and you can read more articles at this link: Click Here to explore my articles.

  1. New LINQ Methods in .NET 9: Index, CountBy, and AggregateBy
  2. Working with JSON in .NET Core: Newtonsoft.Json, NetJSON, and System.Text.Json
  3. Implement a retry policy in .NET 6 Applications with Polly
  4. Understanding Model Binding in ASP.NET Core with .NET 8
  5. Data Conversions in C# with SuperConvert


Similar Articles