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:
- Value Type and Reference Type
- C# - Nullable Types
- How does a Nullable type work behind the scenes?
- Why are Nullable considered a value type?
- how are nullable types implemented under the hood in .net?
- Nullable implementation
- And our friend Ali Ahmadi ;)
Powered by Froala Editor