Understanding Nullable Value Types in C#
Tags: csharp, dotnet
Published: 2020-01-04 05:12:06

---
title: Understanding Nullable Value Types in C#
published: true
date: 2019-12-28 00:00:00 UTC
tags: csharp, dotnet
canonical_url: https://sahansera.dev/nullable-value-types-in-csharp/
---

![nullable values ide](https://sahansera.dev/static/516d52281c83ec212c41b011dada9e79/11d19/nullable-values-ide.png)

I recently started picking out different topics that I like to learn more about. One such thing I wanted to have a closer look at is “Nullable **value types** in C#“.

We first need to understand the ‘why’ behind nullable value types.

Let’s have a look at this class:

```csharp
public class User
{
    public string Name { get; set; }
    public int DaysSinceLastLogin { get; set; }
    public DateTime RegistrationTimestamp { get; set; }

    public User()
    {
        DaysSinceLastLogin = -1; // Magic Number
        RegistrationTimestamp = DateTime.MinValue; // Magic Number
    }
}
```

When designing a class like this, we often come across situations where we want to default a value type to a `null` or tell the program that there’s no actual value set.

In the above example, since `RegistrationTimestamp` and `DaysSinceLastLogin` are value types, we can’t represent that an actual value exists, we need to default them to the magic numbers we chose. Two major drawbacks of this approach are, we wouldn’t know what the actual magic numbers represent and if we decide to change the value we need to do some plumbing to get around it.

For a much cleaner implementation we can make use of C#‘s out of the box Nullable Value Types.

## Definition of the Nullable Value Types

The MSDN definition goes as follows:

> A nullable value type T? represents all values of its underlying [value type](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/value-types) T and additional null value.

Let’s think of `DaysSinceLastLogin` from the above example. Its type is [Int32](https://docs.microsoft.com/en-us/dotnet/api/system.int32) which spans from -2,147,483,648 to 2,147,483,647. Obviously, in our context, we don’t need negative numbers to represent how many days have elapsed since the last login of the user (we could have used `uint` instead, but let’s not get bogged down with such details). For the sake of the argument, let’s look at how to can convert it to a Nullable value Type.

![nullable diagram](https://sahansera.dev/static/66c46039d1e72481382675e4f40707e8/f67cc/nullable-diagram.jpg)

What this does is, essentially, it wraps our value type of `int` in a [Nullable struct](https://docs.microsoft.com/en-us/dotnet/api/system.nullable-1?view=netcore-3.1); which allows us to assign it an integer value or a `null`

## Refactoring our code with Magic Numbers

```csharp
public class User
{
    public string Name { get; set; }
    public Nullable<int> DaysSinceLastLogin { get; set; }
    public Nullable<DateTime> RegistrationTimestamp { get; set; }

    public User()
    {
        DaysSinceLastLogin = null;
        RegistrationTimestamp = null;
    }
}
```

Now we can simply assign `null`s to our `DaysSinceLastLogin` and `RegistrationTimestamp`. But, C# is known for its nice syntactic sugar. Let’s sugarcoat it like so:

```csharp
public class User
{
    public string Name { get; set; }
    public int? DaysSinceLastLogin { get; set; }
    public DateTime? RegistrationTimestamp { get; set; }
}
```

This is beautiful, and behind the scenes, it still wraps in a `Nullable<T>` struct. Another good thing is that now we don’t need to explicitly specify `null` to `DaysSinceLastLogin` and `RegistrationTimestamp`. We all know that `null`s are a [billion dollar mistake](https://en.wikipedia.org/wiki/Tony_Hoare), but still, could have been worse 😁

## Convenience properties and methods of Nullable<t></t>

- [`.HasValue`](https://docs.microsoft.com/en-us/dotnet/api/system.nullable-1.hasvalue?view=netcore-3.1) - `true` if it has a value; false if null
- [`.Value`](https://docs.microsoft.com/en-us/dotnet/api/system.nullable-1.value?view=netcore-3.1) - Gives us the underlying value. However, this will throw an `InvalidOperationException` if you try to access a value whose `.Value` property is `false`
- [`.GetValueOrDefault()`](https://docs.microsoft.com/en-us/dotnet/api/system.nullable-1.getvalueordefault?view=netstandard-2.1) - Underlying value or default. Eg: for an integer whose value has not been set, will return `0`-[`.GetValueOrDefault(T)`](https://docs.microsoft.com/en-us/dotnet/api/system.nullable-1.getvalueordefault?view=netstandard-2.1#System_Nullable_1_GetValueOrDefault__0_) - Value or a specified default value.

In my next post, we will look at how we can access and check for null values in C#. Until then ✌️

## References

1. [https://docs.microsoft.com/en-us/dotnet/api/system.nullable-1?view=netcore-3.1](https://docs.microsoft.com/en-us/dotnet/api/system.nullable-1?view=netcore-3.1)