In C#, there are two types of data types: ValueType and ReferenceType. These types have their own unique characteristics. One of the features we want to discuss in this article is the ability to assign a Null value to ValueTypes. ReferenceTypes do not store the actual data; instead, they store the address related to the data. In fact, ReferenceTypes behave like a pointer, keeping the address where the actual data is stored. When we assign a Null value to a ReferenceType, the address becomes Null, meaning it doesn't point anywhere.

However, ValueTypes do not behave this way; they store the actual data, not the address of the data. Therefore, we cannot store a Null value inside a ValueType. To address this issue, C# introduced a struct called "Nullable" in C# 2, which allows us to consider Null values for ValueTypes as well, with some differences.

Nullable<int> number = null;

The Nullable struct is written in a generic way, and its input type must be a ValueType. For example, you cannot send a ReferenceType as input to Nullable.

Nullable<Type> type = typeof(Type);//Compilation error!

Nullable includes two properties, Value and HasValue. The Value property is only assigned a value when it has been initialized by its constructor. If the stored value is Null, and we try to access the Value property, we encounter a Null reference error.

public bool HasValue 
{
    [System.Runtime.Versioning.NonVersionable]
    get
    {
         return hasValue;
    }
} 

public T Value 
{
    get 
    {
         if (!hasValue) 
         {
              ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_NoValue);
         }
          return value;
     }
}

We can store a Null value in a Nullable int variable. However, behind the scenes, something else happens. In reality, the code:

Nullable<int> number = null;

Is transformed into:

Nullable<int> number = new Nullable<int>();

This transformation is hidden from the developer's perspective, and the compiler does it automatically. The reason for this is that we cannot store a Null value inside a ValueType. Therefore, when we define a Nullable variable of type int, the default value for that type (0 for int) is placed in memory, and a Null value for ValueTypes is not actually stored in memory.

Nullable struct in C# is a struct that contains some exceptions that developers cannot implement. For example, if you obtain all the code related to Nullable and define a new struct called CustomNullable, you cannot store Null values inside it because the Nullable struct in C# is identified as a special struct that can perform different tasks.

Sources used for this article:

Powered by Froala Editor

Comments