简体   繁体   中英

Using the Null Conditional Operator to check values on objects which might be null

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.

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?

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
}

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM