66

I have this very simple example:

class Program
{
    class A
    {
        public bool B;
    }

    static void Main()
    {
        System.Collections.ArrayList list = null;

        if (list?.Count > 0)
        {
            System.Console.WriteLine("Contains elements");
        }

        A a = null;

        if (a?.B)
        {
            System.Console.WriteLine("Is initialized");
        }
    }
}

The line if (list?.Count > 0) compiles perfectly which means that if list is null, the expression Count > 0 becomes false by default.

However, the line if (a?.B) throws a compiler error saying I can't implicitly convert bool? to bool.

Why is one different from the other?

6
  • Which framework version is this ? Commented Jun 29, 2016 at 15:29
  • 14
    @Veverke it is not the .NET framework version that conrolls this, it is the compiler you use. .? was introduces in C# 6 which was included with Visual Studio 2015 and newer Commented Jun 29, 2016 at 15:30
  • 1
    See What exactly does ‘lifted’ mean? Commented Jun 29, 2016 at 15:30
  • If you make the property "public bool? B" on class A, does it work? Commented Jun 29, 2016 at 15:31
  • @BrianMains no, it does not. See the accepted answer. Commented Jun 29, 2016 at 16:35

2 Answers 2

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

2 Comments

Thanks. I didn't realize that list?.Count basically becomes int? tmp = list?.Count and then of course tmp > 0 evaluates to false. This was the missing piece.
An important point is "if, however, requires a bool". This is why one can express a?.B == true and it should compile. As obvious as that is, it can elude someone looking too closely at syntax.
43

In your first case (list?.Count) the operator returns an int? - a nullable int.
The > operator is defined for nullable integers so that if the int? has no value (is null), the comparison will return false.

In your second example (a?.B) a bool? is returned (because if a is null, neither true nor false but null is returned). And bool? cannot be used in an if statement as the if statement requires a (non-nullable) bool.

You can change that statement to:

if (a?.B ?? false)

to make it work again. So the null-coalescing operator (??) returns false when the null-conditional operator (?.) returned null.

Or (as TheLethalCoder suggested):

if (a?.B == true)

8 Comments

Would if (a?.B == true) give the same effect?
@TheLethalCoder While C# limits bool values to false and true, the .NET Framework does not, and non-C# methods may give you what can be in pseudo-C# as (bool) 2. Such a value is true enough to enter an if block if used as the condition, but does not compare equal to true.
Whether if (a?.B == true) works or not, when I see it, I have the gut instinct to chime in "don't compare booleans to true (or false), use them directly," as would normally be appropriate when someone writes if (someCondition == true) instead of if (someCondition). I'm not sure what to make of a construction that ends up encouraging (... == true).
@JoshuaTaylor it's not comparing a bool to true, but a bool?
@RenéVogt Yes, I understand that; my point is that it's jarring to see a place where == true is the right thing.
|

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.