4

Can someone please explain the logic of the null-conditional operator in if statements?

Imagine the following code

List<string> items = null;
if (items?.Count == 0)
{
    Console.WriteLine("error");
}
else
{
    Console.WriteLine("OK");
}

The above will print OK. Why does it compile when the next block would not?

if (items?.Any())    // won't compile but if (items?.Count() == 0) would
{
    ...
}

I am guessing the ?. will stop execution when null detected and the entire if is skipped but why is it not the case with "?.Any()"? Just because it's a method whereas "count" is a property?

And why does the Linq extension method Any() require an explicit conversion from Nullable to bool where Count() == 0 compiles with no conversion Nullable to int required?

2
  • 2
    There is an overload on == to lift the comparison and still return true/false, so the magic is in the == operator on Nullable<T>. If you try if (items?.Any() == true) it will compile. Commented May 6, 2021 at 10:18
  • 1
    Note that, in C# 9, you can write this as if (items is { Count: > 0 }). You may or may not find that clearer. Commented May 6, 2021 at 10:22

2 Answers 2

11

if items is null, then items?.Count is null, too.
and null == 0 is a comparison that results in false. so the if is happy.

but items?.Any() will also be null - and if(null) is invalid, because null is not a boolean, and cannot be converted to one.

so you simply have to provide a fallback boolean value:

if (items?.Any() ?? false) {

}

will do the trick

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

7 Comments

if (items?.Any() == true) is more readable I think
@HansKilian that's a matter of preference, i (obviously) root for the null coalesce operator. but it would be interesting to see if there's differences in performance.
Readability is generally more important than performance, I think. At least on the systems I work on. I leave performance to the compiler :) But you're right, of course, that what's more readable is a matter of preference.
@David It's because both 0 and null can be converted to an int? (a nullable int).
|
7

Consider the null case.

In if (items?.Count == 0) that becomes if (null == 0) and that gives false.

But in if (items?.Any()) it becomes if (null) and that is invalid.

You can use if (items?.Any() == true) or if (items?.Any() ?? false) or something similar.

I notice that items.Count == 0 is an error but items == null returns Ok in your first example.
That is odd.

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.