C#’s null-coalescing operator (??) simplifies the syntax required to say “the value of an expression is x unless x is null in which case the value is y.”
Suppose we want to set the variable salary to a value fetched from the database. However, if the database returns null, salary should be set to 0.
In Longhand
Here’s one way to fulfill these requirements:
decimal? salaryFromDatabase = fetchSalaryFromDatabase(); decimal salary; if (salaryFromDatabase != null) { // A cast must be used to convert salaryFromDatabase (a nullable decimal) to a non-nullable decimal. salary = (decimal)salaryFromDatabase; } else { salary = 0m; }
Conditional (?:) Simplicity
By using the conditional operator (?:), much verbosity can be eliminated:
decimal? salaryFromDatabase = fetchSalaryFromDatabase(); decimal salary = (salaryFromDatabase != null)? (decimal)salaryFromDatabase : 0m;
At first glance, it might even seem we could simplify this even further to—
decimal salary = (fetchSalaryFromDatabase() != null)? (decimal)fetchSalaryFromDatabase() : 0m;
—but this has the undesirable effect of calling fetchSalaryFromDatabase() twice when that method returns a non-null value, resulting in two database queries. (The method will be called once to see if it returns null and, if it does not, a second time to determine the value to use for salary.)
A True One-Liner
Using the null-coalescing operator (??), we can simplify our introductory example to a single line:
decimal salary = fetchSalaryFromDatabase() ?? 0m;
The method salaryFromDatabase() will only be called once. If it returns a non-null value, salary will be set to the returned value without being called a second time.
Other Examples
-
Daisy-Chaining
int value = possibleValue1 ?? possibleValue2 ?? possibleValue3 ?? possibleValue4 ?? 0;
Note: The right-most value cannot be a nullable type if the result is being assigned to a non-nullable variable. Thus, the (non-null) fallback value of 0.
-
Implementing the Null-Object pattern
public Date DateFactory() { // other code.... return date ?? new NullDate(); }
Notice how the operator’s use is not limited to variable assignment. In this case, it’s being used to determine a method’s return value.