Returning to the distinction between value and reference types, a value type stores its value directly in the variable, while a reference type stores an address to another location in memory that has been allocated to hold the value. This is why reference types can be
null - this indicates they aren’t pointing at anything. In contrast, value types cannot be null - they always contain a value. However, there are times it would be convenient to have a value type be allowed to be null.
For these circumstances, we can use the Nullable<T> generic type, which allows the variable to represent the same values as before, plus
null. It does this by wrapping the value in a simple structure that stores the value in its
Value property, and also has a boolean property for
HasValue. More importantly, it supports explicit casting into the template type, so we can still use it in expressions, i.e.:
Nullable<int> a = 5; int b = 6; int c = (int)a + b; // This evaluates to 11.
However, if the value is
null, we’ll get an
InvalidOperationException with the message “Nullable object must have a value”.
There is also syntactic sugar for declaring nullable types. We can follow the type with a question mark (
int? a = 5;
Which works the same as
Nullable<int> a = 5;, but is less typing.