C# Null propagating operator / Conditional access expression & if blocks
It won't work this way. You can just skip the explanation and see the code below :)
As you know ?.
operator will return null if a child member is null. But what happens if we try to get a non-nullable member, like the Any()
method, that returns bool
? The answer is that the compiler will "wrap" a return value in Nullable<>
. For example, Object?.Any()
will give us bool?
(which is Nullable<bool>
), not bool
.
The only thing that doesn't let us use this expression in the if
statement is that it can't be implicitly casted to bool
. But you can do comparison explicitly, I prefer comparing to true
like this:
if (c?.Object?.Any() == true)
Console.Write("Container has items!");
Thanks to @DaveSexton there's another way:
if (c?.Object?.Any() ?? false)
Console.Write("Container has items!");
But as for me, comparison to true
seems more natural :)
Null-conditional operator would return null
or the value at the end of expression. For value types It will return result in Nullable<T>
, so in your case it would be Nullabe<bool>
. If we look at the example in the document for Upcoming Features in C# (specified here), it has an example:
int? first = customers?[0].Orders.Count();
In the above example, instead of int
, Nullable<int>
would be returned. For bool
it will return Nullable<bool>
.
If you try the following code in Visual Studio "14" CTP:
Nullable<bool> ifExist = c?.Objects?.Any();
The result of the above line would be a Nullable<bool>
/bool?
. Later you can do the comparison like:
Using null-coalescing operator ??
if (c?.Object?.Any() ?? false)
Using Nullable<T>.GetValueOrDefault
Method
if ((c?.Objects?.Any()).GetValueOrDefault())
Using comparison against true
if (c?.Objects?.Any() == true)
var x = c?.Objects?.Any()
is going to give you a nullable boolean, and as others have said, this means you can use an equality operator like this
x == true
or you can use null coalescing like this to have your result not be nullable
var x = c?.Objects?.Any() ?? false
But, personally, I think that 3-state (nullable) booleans are code smell. Even if this one is practically invisible, its existence should encourage you to think about what you are actually trying to do and determine if a nullable boolean is actually the way to go. In this case, I think that what you really want to do is something like this -
var objects = c?.Objects ?? Enumerable.Empty<Object>();
if (objects.Any())
{
...
}
Put that in an extension method and it will be even more succinct -
public static bool IsNullOrEmpty<T>(this IEnumerable<T> collection)
{
return !(collection ?? Enumerable.Empty<T>()).Any()
}