Just to demonstrate the concept in an extremely simple manner, consider the following code:

List<string> list = null;
int count = list.Count;

It’s pretty obvious that if you try to run the above code, you’re going to get a NullReferenceException, because you’re trying to access the Count property of an object that is null.

Now, the example above can seem dumb because it’s pretty obvious that the list is null, but sometimes objects can come from external sources or user input, and so you have to be careful how you handle them. In this case we can work defensively by adding a null check:

That’s okay. But it can get pretty messy when there is a chain of references involved. Consider a binary tree, for instance.

var something = binaryTree1.LeftChild.LeftChild.Name;

If we were to write defensive conditionals for this, you effectively need a null check for each access.

List<string> list = null;
int? count = list?.Count;

The use of the safe navigation operator involves putting a question mark before the dot operator, as shown above. If list happens to be null (which it is in this case), then the Count property is not accessed, and null is immediately returned. Since list?.Count may return either a number or null, the count variable must now be nullable.

The safe navigation operator pays off pretty nicely when you have more complex reference accesses:

var something = binaryTree1?.LeftChild?.LeftChild?.Name;

It also works pretty nicely with the null-coalescing operator.

List<string> list = null;
int count = list?.Count ?? 0;

We can even use it to guard access to array elements when the array is null: