ICanHazValue?

Joel Lyons
Building Degreed
Published in
2 min readJun 10, 2019

There seems to be some debate in the .NET community about using nullable value types. Here are some examples of declaring nullable value types.

Nullable<int> count;
DateTime? occurred; // short-hand for Nullable<DateTime>

But, what’s the best way to check whether such a nullable value type is currently null (ie: empty)? This is the debate!

The generic Nullable<T> struct, which is used to make any value type nullable, has a HasValue property, answering our question.

int? count = GetCount();
DateTime? occurred = GetDateOccurred();

bool hasCount = count.HasValue;
bool hasOccurred = occurred.HasValue;

But, you can also compare it to null, just as you would with any (nullable) reference type.

int? count = GetCount();
DateTime? occurred = GetDateOccurred();
Address address = GetAddress(); // reference types are nullable
bool hasCount = count != null;
bool hasOccurred = occurred != null;
bool hasAddress = address != null;

Hmm…look at how consistent that is! I like to treat all nullable types the same. To me, “nullable” means “might be null”. So before I can use it, I need to make sure it is not null. My [pseudocode] pattern is:

if (object is not null)
{
safely use object;
}

So, in practice, doing this…

DateTime? d = GetDate();    // a nullable value type
if (d != null)
{
Show(d.Value);
}

is consistent with doing this…

Person p = GetPerson();    // reference types already nullable
if (p != null)
{
Show(p.Name);
}

Why use a special HasValue check when you can use a consistent pattern for all nullable types? Just because one is a nullable reference type and one is a nullable value type? For years, we’ve compared things to null before we use them, not because they are reference types, but because they might be null (because they are null-able).

It also seems natural after declaring that I want something to be nullable, to then compare it to, wait for it… null, versus calling HasValue which doesn’t even have the word “null” in it! I guess things would be different if the wrapper was actually called something like ICanHazValue<T>.

ICanHazValue<int> count = GetCount();
if (count.HasValue)
{
total += count.Value;
}

One more thing to consider: C# 8 supports nullable reference types. That allows code like this…

Person? p = GetPerson();    // explicitly nullable reference type
if (p != null) // note HasValue isn't even an option!
{
Show(p.Name);
}

So, shouldn’t we get in the habit of doing this as well?

DateTime? d = GetDate();   // explicitly nullable value type
if (d != null)
{
Show(d.Value);
}

--

--