12

Why this code works:

if (list?.Any() == true)

but this code doesn't:

if (list?.Any())

saying Error CS0266 Cannot implicitly convert type 'bool?' to 'bool'

So why is it not a language feature making such an implicit conversion in the if statement?

Cornelius Roemer
  • 1,853
  • 13
  • 32
Centro
  • 3,702
  • 1
  • 22
  • 30
  • 4
    You mean why doesn't the `if` statement accept a `bool?` condition? It feels to me like it's pretty ambiguous which way you want to go if the result is null. You're defaulting to false (effectively) but in other cases you'd want to default to true. – Jon Skeet Aug 09 '17 at 17:21
  • `list?.Any()` has the potential to be `null` if list is null. And given that Any returns bool it has the potential to return a bool. thus nullable boolean at compile time – Nkosi Aug 09 '17 at 17:21
  • But beyond this, unless Mads or someone else on the C# design team answers, you're basically going to get speculation. – Jon Skeet Aug 09 '17 at 17:21
  • 10
    `if (null == true)` is legal, but `if (null)` isn't. – hatchet - done with SOverflow Aug 09 '17 at 17:24
  • 2
    Note that your final option will throw an exception if `list` is null. That's not good. – Jon Skeet Aug 09 '17 at 17:26
  • Also, for something from person who should know (Eric Lippert): [null is not false pt1](https://blogs.msdn.microsoft.com/ericlippert/2012/03/26/null-is-not-false/) and [null is not false pt2](https://blogs.msdn.microsoft.com/ericlippert/2012/04/12/null-is-not-false-part-two/) – hatchet - done with SOverflow Aug 09 '17 at 17:42
  • see https://softwareengineering.stackexchange.com/questions/313779/optimal-way-to-use-null-conditional-operators-in-boolean-expressions – juFo Jun 21 '19 at 08:05

1 Answers1

7

An if statement will evaluate a Boolean expression.

bool someBoolean = true;

if (someBoolean)
{
    // Do stuff.
}

Because if statements evaluate Boolean expressions, what you are attempting to do is an implicit conversion from Nullable<bool>. to bool.

bool someBoolean;
IEnumerable<int> someList = null;

// Cannot implicity convert type 'bool?' to 'bool'.
someBoolean = someList?.Any();

Nullable<T> does provide a GetValueOrDefault method that could be used to avoid the true or false comparison. But I would argue that your original code is cleaner.

if ((list?.Any()).GetValueOrDefault())

An alternative that could appeal to you is creating your own extension method.

public static bool AnyOrDefault<T>(this IEnumerable<T> source, bool defaultValue)
{
    if (source == null)
        return defaultValue;

    return source.Any();
}

Usage

if (list.AnyOrDefault(false))
Derrick Moeller
  • 4,271
  • 2
  • 20
  • 42
  • 2
    I interpreted the question as "why doesn't `if` accept a `bool?` condition?" – Jon Skeet Aug 09 '17 at 17:25
  • So the question is why an explicit conversion is ok but the implicit one not? This is not about accepting `bool?` condition. – Centro Aug 09 '17 at 17:37
  • @Centro Because the explicit conversion will throw an exception if you try to cast `null`. Implicit conversions throwing exceptions should be avoided at all costs, so we can't have the implicit conversion act the same way. We also can't implicitly convert `null` to `false` because that's unreasonable. For example you'd probably want `if( !list?.Any() )` to be the opposite of `if( list?Any() )`. But if `list == null` then both of those would end up being `if( null )`. – Kyle Aug 09 '17 at 17:45
  • I would also add a default value to the defaultValue parameter `public static bool AnyOrDefault(this IEnumerable source, bool defaultValue = false)` so that you can call the method with no parameters like `if (list.AnyOrDefault())` – Bill Lefler Mar 06 '21 at 14:05