One of my favorite new features of C# 6 is the null-conditional operator. While it is certainly possible to go without this feature, it will greatly simplify the code you write to avoid NullReferenceExceptions. To give you an idea of what this will do for you, imagine getting rid of most of the “if (x != null)” statements in your code! There are three uses of the null-conditional operator: member access, index access, and delegate invocation.
Member Access
Member Access will probably be one of the more common uses of the null-conditional operator. Let’s take a look at what our code would look like before the null-conditional was available using a simple NullDemoData class that has an Id and a Name and a method that returns the Name property:
// The OLD way public string GetNameFromItem(NullDemoData item) { if (item != null) { return item.Name; } return null; // or: return item != null ? item.Name : null; }
Even though we are doing something really simple, it requires several lines of code. Now with the null-conditional operator, we can simplify our code to this:
public string GetNameFromItem(NullDemoData item) { return item?.Name; }
Much better. By adding the “?” before .Name, our method will simply return null if item is null and it will return the value of item.Name if it is not null. You can see that this is especially nice if you have a larger hierarchy of objects, where we can reduce multiple if-null checks to a single line:
return order?.Header?.ShipToAddress?.City;
If any object in the hierarchy is null, it will short-circuit and return null instead of throwing a NullReferenceException.
Value Types
The examples above are using reference types which can hold a null value, but what about a value type such as an integer? If you use a null-conditional operator with a value type, you should make use of nullable types, so for an int, it would look like this:
int? id = item?.Id;
But depending on your situation, a better option might be to use the null-conditional operator along with the null-coalescing operator (??) which will convert any null on the left side of the operator to the value on the right:
public int GetIdFromItem(NullDemoData item) { return item?.Id ?? 0; }
As you can see, our method returns an int instead of a Nullable<int>. This is very powerful due to the way the null-conditional operator short-circuits any null value: if any object in your chain of hierarchy is null, it will return the value you provide to the right of the ?? operator:
int orderCount = order?.Items?.Count() ?? 0;
Index Access
Very similar to member access, we can use the null-conditional operator before accessing the index of a collection. Here’s an example that combines member access, index access, and the null-coalescing operator to return the Name of the first item in a collection, but returns “No Name” if either the collection or Name is null:
public string GetFirstNameFromList(IList<NullDemoData> list = null) { return list?[0]?.Name ?? "No Name"; }
Invoking Delegates
The last use of the null-conditional operator lets us simplify how we invoke a delegate. If we try to invoke a delegate that does not have any registered handlers, it will be null and throws a NullReferenceException. The old way to invoke a delegate would be to assign it to a local variable to be thread-safe, check for null, then invoke it:
// The OLD way public void RaiseEventWithNullCheck() { var onDataChanged = DataChanged; if (onDataChanged != null) { onDataChanged(this, new EventArgs()); } }
Now we can simplify this to a single line using the null-conditional operator and the Invoke() method:
public void RaiseEvent() { DataChanged?.Invoke(this, new EventArgs()); }
And yes, you need to use ?.Invoke() instead of DataChanged?(sender, args) due to the syntax ambiguities that would arise from making the call without the Invoke().
Take a look at an example solution with unit tests on GitHub.
The post Null-Conditional Operators – Day 2 – Visual Studio 2015 appeared first on Falafel Software Blog.