Nullable types are specific wrappers around the value types that allow storing the data as null values.This provides opportunity for types which does not allow lack of value (i.e value as null) to be used as reference types and to accept both normal values and the special one null.Thus nullable types holds an optional value.
Wrapping of nullable types can be done in two ways:
Nullable types are reference types i.e. they are reference to an object in the dynamic memory, which contains their actual value. They may or may not have a value and can be used as normal primitive data types, but with some specifics, which are illustrated in the following example:
int i = 5;
int? ni = i;
Console.WriteLine(ni); // 5
// i = ni; // this will fail to compile
Console.WriteLine(ni.HasValue); // True
i = ni.Value; Console.WriteLine(i); // 5
ni = null;
Console.WriteLine(ni.HasValue); // False
//i = ni.Value; // System.InvalidOperationException
i = ni.GetValueOrDefault();
Console.WriteLine(i); // 0
The example above shows how a nullable variable (int?) can have a value directly added even if the value is non-nullable (int). The opposite is not directly possible. For this purpose, the nullable types’ property Value can be used. It returns the value stored in the nullable type variable, or produces an error (InvalidOperationException) during program execution if the value is missing (null). In order to check whether a variable of nullable type has a value assigned, we can use the Boolean property HasValue. Another useful method is GetValueOrDefault(). If the nullable type variable has a value, this method will return its value, else it will return the default value for the nullable type (most commonly 0).