287

I was wondering what was the most clean and understandable syntax for doing condition checks on nullable bools.

Is the following good or bad coding style? Is there a way to express the condition better/more cleanly?

bool? nullableBool = true;
if (nullableBool ?? false) { ... }
else { ... }

especially the if (nullableBool ?? false) part. I don't like the if (x.HasValue && x.Value) style ...

(not sure whether the question has been asked before ... couldn't find something similar with the search)

FireSnake
  • 2,983
  • 2
  • 16
  • 9
  • 2
    Beginning with C# 7.0, you can use the is operator with a type pattern to both examine an instance of a nullable value type for null and retrieve a value of an underlying type:int? a = 42; if (a is int valueOfA) { – Masoud Jul 22 '20 at 21:27

13 Answers13

483

I think a lot of people concentrate on the fact that this value is nullable, and don't think about what they actually want :)

bool? nullableBool = true;
if (nullableBool == true) { ... } // true
else { ... } // false or null

Or if you want more options...

bool? nullableBool = true;
if (nullableBool == true) { ... } // true
else if (nullableBool == false) { ... } // false
else { ... } // null

(nullableBool == true) will never return true if the bool? is null :P

Artiom Chilaru
  • 11,811
  • 4
  • 41
  • 52
  • 9
    I didn't realize that nullable comparison was meaningful like this. Details can be found at https://msdn.microsoft.com/en-us/library/2cf62fcy.aspx – Micah Zoltu Oct 17 '15 at 17:55
  • 11
    The relevant part of the [docs](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/nullable-value-types): `For the equality operator ==, if both operands are null, the result is true, if only one of the operands is null, the result is false; otherwise, the contained values of operands are compared.` – Eric Mutta Mar 17 '21 at 19:33
  • 1
    Although `(nullableBool == true)` will never return true if it's `null`, a null value in a nullable bool can't be considered `false`, and `&&` and `||` operators will fail to compile when used against nullable bools, which I personally find a bit of a pain as, in the context of a boolean condition, anything not `true` could be considered `false`, while still allowing an equality check for the null value itself to return true. – controlbox Feb 20 '22 at 02:01
  • @controlbox I think you are not right. Boolean means 0 = false and everything else is true. Maybe that's the reason why they didn't allow `if (nullableBool) ...` I can't imagine to voluntarily use nullable booleans. I hate "maybe" as an answer to a "yes or no?" question. – The incredible Jan Sep 21 '22 at 13:15
  • @TheincredibleJan I'd agree if null was considered a 'value', but it isn't (hence .HasValue() returning false), so in the context of a Boolean expression, true is the only non-false value, and therefore null (the absence of a value) can't also be considered true. – controlbox Sep 25 '22 at 22:22
108

How about using GetValueOrDefault, which is pretty self-explaining and allows to use whatever default you want:

if (nullableBool.GetValueOrDefault(false)) {
}
Lucero
  • 59,176
  • 9
  • 122
  • 152
  • 9
    Depending the context this approach might throw `System.NotSupportedException: LINQ to Entities does not recognize the method 'Boolean GetValueOrDefault()' method, and this method cannot be translated into a store expression.` – Nano Taboada Dec 27 '12 at 20:00
  • 3
    I like this approach as it also works in a non-if statement (i.e. assignment). – paultechguy Mar 17 '18 at 14:06
64

You may not like it, but personally I find

if (x.HasValue && x.Value)

the most readable. It makes it clear you are working with a nullable type and it makes it clear you are first checking whether the nullable type has a value before acting on it conditionally.

If you take your version and replace the variable with x also it reads:

if (x ?? false)

Is that as clear? Is it obvious x is a nullable type? I'll let you decide.

Dan Diplo
  • 25,076
  • 4
  • 67
  • 89
45

Another way is to use constant pattern matching:

if (nullableBool is true) {}
if (nullableBool is false) {}
if (nullableBool is null) {}

Unlike the operator ==, when reading the code, this will distinguish the nullable type check from ordinary "code with a smell".

Vladimir Shiyanov
  • 1,236
  • 16
  • 18
29

If you want to treat a null as false, then I would say that the most succinct way to do that is to use the null coalesce operator (??), as you describe:

if (nullableBool ?? false) { ... }
Oded
  • 489,969
  • 99
  • 883
  • 1,009
21

Just think of bool? as having 3 values, then things get easier:

if (someNullableBool == true)     // only if true
if (someNullableBool == false)    // only if false
if (someNullableBool == null)     // only if null
12

Actually I think that (nullableBool ?? false) is a legitimate option especially when you are trying to evaluate a nullable bool in linq.

For example:

array.Select(v => v.nullableBool ?? false)
(from v in array where v.nullableBool ?? false)

Is cleaner in my opinion as opposed to:

array.Select(v => v.nullableBool.HasValue ? v.nullableBool.Value : false)
(from v in array where v.nullableBool.HasValue ? v.nullableBool.Value : false)
Zze
  • 18,229
  • 13
  • 85
  • 118
9

Use extensions.

public static class NullableMixin {
    public static bool IsTrue(this System.Nullable<bool> val) {
        return val == true;
    }
    public static bool IsFalse(this System.Nullable<bool> val) {
        return val == false;
    }
    public static bool IsNull(this System.Nullable<bool> val) {
        return val == null;
    }
    public static bool IsNotNull(this System.Nullable<bool> val) {
        return val.HasValue;
    }
}


Nullable<bool> value = null;
if(value.IsTrue()) {
// do something with it
}
Orace
  • 7,822
  • 30
  • 45
Andrey Frolov
  • 1,534
  • 10
  • 19
8

Lets check how the comparison with null is defined:

static void Main()
    {
        Console.WriteLine($"null != null  => {null != null}");
        Console.WriteLine($"null == null  => {null == null}");
        Console.WriteLine($"null != true  => {null != true}");
        Console.WriteLine($"null == true  => {null == true}");
        Console.WriteLine($"null != false => {null != false}");
        Console.WriteLine($"null == false => {null == false}");
    }

and the results are:

null != null  => False                                                                                                                                                                                                                                  
null == null  => True                                                                                                                                                                                                                                   
null != true  => True                                                                                                                                                                                                                                   
null == true  => False                                                                                                                                                                                                                                  
null != false => True                                                                                                                                                                                                                                   
null == false => False

So you can safely use:

// check if null or false
if (nullable != true) ...

// check if null or true
if (nullable != false) ...

// check if true or false
if (nullable != null) ...
Sz. Moncz
  • 109
  • 1
  • 5
  • Im just wondering why can't we do if(nullable) .... that would be handle but need to be treated with caution `if(nullable)...else if(!nulllable)...else..` – IronHide May 10 '18 at 09:54
  • I would say during last years the coding style (due to availability of tools like stylecop, analyzers, etc.) is more and more preferring unambiguous, clear, "intention confirming" code (e.g. recommending to use unneeded parentheses just to confirm the intended usage of operators priority, or using various annotation/contract systems). IMO introducing such a syntax would cause much more confusion due to the level of unclarity how nullables are handled than benefit. – Sz. Moncz May 17 '18 at 17:42
3

If you only want to test for true against null/false, One I've just used and reads quite well is

bool? someCondition = null
if (someCondition.Equals(true))
...
ds4940
  • 3,382
  • 1
  • 13
  • 20
  • 2
    Are you not getting a null reference exception here? – Chase Florell Feb 26 '20 at 06:38
  • @ChaseFlorell I had to double check this in VS Interactive window.. So the thing to remember is that the type of somecondition is Nullable.You can still call the the methods inherited from object (such as Equals), HasValue and GetValueOrDefault, but not Value – ds4940 Feb 26 '20 at 10:25
  • 1
    interesting, I can see that now. Still sketchy for reference types https://dotnetfiddle.net/8cAI21 – Chase Florell Feb 26 '20 at 15:33
0

I think its up to you. I certainly think the .HasValue approach is more readable, especially with developers not familiar with the ?? syntax.

The other point of a nullable boolean type is that it is tristate, so you may want to do something else when it is just null, and not default to false.

James Westgate
  • 11,306
  • 8
  • 61
  • 68
0

Given enum

public enum PublishMode { Edit, View }

you can do it like here

 void MyMethod(PublishMode? mode)
    {
       var publishMode = mode ?? PublishMode.Edit;

//or
       if (mode?? PublishMode.Edit == someValue)
       ....
    }
Gopher
  • 917
  • 6
  • 18
0

If you're in a situation where you don't have control over whether part of the condition is checking a nullable value, you can always try the following:

if( someInt == 6 && someNullableBool == null ? false : (bool)someNullableBool){
    //perform your actions if true
}

I know it's not exactly a purist approach putting a ternary in an if statement but it does resolve the issue cleanly.

This is, of course, a manual way of saying GetValueOrDefault(false)

user4593252
  • 3,496
  • 6
  • 29
  • 55
  • 3
    The solution provided in the OP is the same thing, but just with far less code bloat. This isn't at all advantageous to that. – Servy Jan 30 '15 at 16:54