21

I've been playing with C# 6's Null Conditional Operator (more info here).

I really like the syntax and I think it makes the code much more readable however I think it is questionable as to what exactly the code is going to do when you come across checking the value of a property on an object which itself might be null.

For example, if I had a class with a decimal property on it and I wanted a conditional check on the value of that decimal, I would write something like:

if (foo?.Bar > max)
{
   // do something
}

On the surface this looks great... If foo is not null, get the value of Bar and check if it's greater than a maximum value, if it is, do something.

However, what if foo is null?!

This documentation about the new and improved features of C# 6 says something along these lines:

if in fact the value of the object is null, the null-conditional operator will return null. It short-circuits the call to Bar, and immediately returns null, avoiding the programming error that would otherwise result in a NullReferenceException.

I've written a fiddle here which shows that it does indeed work and is doing what I'm expecting it to do however I can't get my head around how it is deciding the result of the condition.

How does the short-circuit equal a false? In my head this code is now going to say "If foo is null, check if null is > max, which is impossible, so return false" or "If foo is null, then foo != null will return false, so you get a false" however the documentation says the null conditional check returns null, not false.

2
  • Interestingly, it will not run do something whether the condition is (bar > max) or (bar <= max). So basically, a null value in a condition will always evaluate to false, no matter what the condition actually is. Commented Aug 21, 2017 at 12:11
  • 1
    You should use (foo?.Bar).GetValueOrDefault(2) to set a value to use for comparison if foo is null. I specified "2" but if you leave out the parameter it defaults to zero. Commented Aug 21, 2017 at 12:23

3 Answers 3

18

How does the short-circuit equal a false?

if (foo?.Bar > max)
{
   // do something
}

is roughly equivalent to:

Decimal? bar = null;
if (foo != null)
    bar = foo.Bar;

if (bar > max)
{
   // do something
}

Thus, the short circuit doesn't equal false. It equals a Decimal? (nullable Decimal) which is then compared to max.

See also: How does comparison operator works with null int?

Sign up to request clarification or add additional context in comments.

7 Comments

This makes sense. The documentation says it returns null but this would mean it is clever enough to know that the null returned is actually a nullable<T> with a value of null... has anyone reflected what the ?. is actually doing internally?
Click on the links in my post @DannyLager . One of them shows how Roslyn lowers it. It basically converts the ?. to something like what I have above (not exactly the same, but close enough).
The documentation says it returns null Fundamentally, it needs to return a null of a specific Type. And given the Bar property was a Decimal, Decimal? is the obvious choice.
Thanks I had looked at the first link but not understood what it was! Second link is very interesting, I didn't know that all operators (except !=) would handle a null in this way although I've never come across an issue with this in the past!
@AkashKC It is a link to Roslyn source code that lowers ?.. As to what lowering is, see stackoverflow.com/a/45772116/34092 . You may enjoy reading msdn.microsoft.com/en-us/magazine/… as well.
|
8

It short-circuits the call to Bar

means stop checking the following steps (.) within an object reference chain if the parent is already null. This means operators like a comparison are not affected because you are using the value instead of moving in the chain. This behaviour is called null propagation. You can find some nice descriptions at Code Project or Dave Fancher.

Using the null conditional operator returns a nullable value like double?. This value is then compared with max. The behaviour of a null in such a comparision is well described by Microsoft:

When you perform comparisons with nullable types, if the value of one of the nullable types is null and the other is not, all comparisons evaluate to false except for != (not equal).

This means:

if (null > max)
{
    //never called
}

Comments

-1

The Null Conditional Operator should be used only for scenarios regarding objects properties's multiple assignments (see objects mapping, etc..) where it could be boring verify every time if occurs the null condition of the property.

Or also for scenarios like the following :

int? count = customers?[0]?.Orders?.Count();  // null if customers, the first customer, or Orders is null 

Using this operator into an if test expression it could lead to unexpected behaviours, for example in your if statements case on fiddler you get a "passed" test (the last if statement) but with a null value, which is obviously not a valid case

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.