We’ve had the null conditional operator for years, since C# 6. You might want to skim that post (which I wrote a few years ago) before reading this one, if you’re unfamiliar with it. Otherwise, I’ll borrow a bit for a quick review, and then we’ll look at what C# 14 added. And if you’d like to mess around with the code below, it’s available in my CSharpDotNetFeatures repo on GitHub.
Null Conditional (a review)
When we’re dealing with nested classes, like the one below for example, we usually have to be really defensive to avoid the dreaded NullReferenceException.
| |
That means checking for null repeatedly when referencing, say, an employee’s name. And since collections are involved, we need to check to make sure they have valid values too. If we just wanted to get the first employee from the first department, we might do something like this:
| |
What the null conditional operators let us do is shorten the above to just this:
| |
At every step along the way, it checks whether it can skip the rest (short-circuit), and just set employeeName == "N/A":
- If
org == null, then it skips everything else and sets employee name to “N/A”. - If
org.Departments == null, it skips the rest and moves on. - If
org?.Departments[0] == nullfor some weird reason, it skips the rest. - And on and on, with
.Employees, then.Employees[0], etc.
Getting a nested value involves a lot less code, which is great.
Null Conditional Assignment
What the null conditional operator hasn’t helped us shorten in the past, though, is setting a value. If any part of the nested objects is null we’ll get an exception, so we have to be careful:
| |
However, with the update in C# 14 that allows using the null conditional operator when assigning a value, we can use the same short-circuiting code here too:
| |
Combined with a feature we got in C# 8, to use the null-coalescing operator ??= during assignment, we can also quickly make sure that existing values aren’t accidentally overwritten:
| |
It could even be used with LINQ when searching through nested collections, to handle the case where whatever we’re searching for isn’t found:
| |
Thoughts
I like that the feature works on both sides of the assignment operator now, which is more consistent. I haven’t used it in a prod environment yet (since it’s brand new), but it definitely seems like it’ll make things more readable … once I’m used to reading it!
In some cases though, the (older) more verbose way could be more readable, and I think readability is really important, especially when multiple devs are working in an app. Heck, when I set an app down and pick it up a year later, I might as well be a different dev for all I remember about it, lol. All-in-all though, it’s a nice addition to the language!
