DEV Community

Jon Stødle
Jon Stødle

Posted on • Originally published at blog.jonstodle.com on

If Statements With Nullable Bools

Nullable bool in C# might sometimes feel a bit of a hassle to work with. I’m here to give you a few tips that took me embarrassingly long to pick up on. I’m hoping this saves you some hassle too.

HasValue and Value

These properties are present on Nullable<T> and have been since generics where introduced. It took me too long to notice them, so here they are. No need to write

bool? nullableBool = true;
bool regularBool;

if (nullableBool != null)
{
    regularBool = (bool)nullableBool;
}

Enter fullscreen mode Exit fullscreen mode

when you can write

bool? nullableBool = true;
bool regularBool;

if (nullableBool.HasValue)
{
    regularBool = nullableBool.Value;
}

Enter fullscreen mode Exit fullscreen mode

HasValue returns true if nullableBool is not null and Value returns a regular bool if nullableBool is not null.

Value also works a lot better when chaining methods:

bool? nullableBool = true;

((bool)nullableBool).ToString();
// or, simply
nullableBool.Value.ToString();

Enter fullscreen mode Exit fullscreen mode

I think the second option is a lot more readable.

GetValueOrDefault

This method on Nullable<T> might not always save characters, but it’s very clear in it’s intent, which I believe accounts for a lot.GetValueOrDefault makes it clear what your code does.So instead of the generic null coalescing

bool? nullableBool = true;
bool regularBool;

if (nullableBool ?? false)
{
    regularBool = nullableBool.Value;
}

Enter fullscreen mode Exit fullscreen mode

you can explicitly say that you want a default value

bool? nullableBool = true;
bool regularBool;

if (nullableBool.GetValueOrDefault(false))
{
    regularBool = nullableBool.Value;
}

Enter fullscreen mode Exit fullscreen mode

As I said, GetValueOrDefault doesn’t necessarily save on characters, but it’s clearly states what you want. This too works better when chaining methods:

bool? nullableBool = true;

(nullableBool ?? false).ToString();
// alternatively
nullableBool.GetValueOrDefault(false).ToString();

Enter fullscreen mode Exit fullscreen mode

Direct variant checking

Again, this is one of those things that took me too long to figure out, so here goes. A simple boolean check might look like this:

bool regularBool;

if (regularBool)
{
    // some code...
}

Enter fullscreen mode Exit fullscreen mode

but that doesn’t work with a bool?, so I used to do something like this

bool? nullableBool = true;

if (nullableBool.HasValue && nullableBool.Value)
{
    // some code...
}

Enter fullscreen mode Exit fullscreen mode

or

bool? nullableBool = true;

if (nullableBool ?? false)
{
    // some code...
}

Enter fullscreen mode Exit fullscreen mode

Turns out, you can just do this instead:

bool? nullableBool = true;

if (nullableBool == true)
{
    // some code...
}

Enter fullscreen mode Exit fullscreen mode

nullableBool == true will evaluate to false if nullableBool is either false or null, in other words: not true. It seems so obvious in retrospect, but I’d become so accustomed to writing if (regularBool) ..., instead of if (regularBool == true) ..., that it didn’t occur to me to write it out in full for bool?s.

The other Nullable<T>s

This does work for the other nullable primitive types too. You can for example shorten this

int? nullableInt = null;
int regularInt;

if (nullableInt.HasValue && nullableInt == 100)
{
    regularInt = nullableInt.Value;
}

Enter fullscreen mode Exit fullscreen mode

to

int? nullableInt = null;
int regularInt;

if (nullableInt == 100)
{
    regularInt = nullableInt.Value;
}

Enter fullscreen mode Exit fullscreen mode

There’s also this case:

int? nullableInt = null;
int regularInt;

if (nullableInt < 100)
{
    regularInt = nullableInt.Value;
}

Enter fullscreen mode Exit fullscreen mode

nullableInt < 100 will evaluate to true if nullableInt has a value, and that value is less than 100. It will however evaluate to false if nullableInt is null. Which one could argue is correct, as nullableInt isn’t a number lower than 100, it’s null (which isn’t a number at all).


I hope you found this interesting, or at least helpful.

Happy coding!

Top comments (0)