Phase 2 of 30 · Topic 2.4

Nullable Value Types (Nullable<T>) vs Nullable Reference Types (NRT)

1Concept

`Nullable<T>` (`int?`) is a genuine 8-byte value type struct with `bool HasValue` and `T Value`. In contrast, Nullable Reference Types (`string?`) are static Roslyn compiler annotations with zero runtime overhead.

2Architecture Diagram

Nullable<int> Layout (8 Bytes):
┌─────────────────────────┬─────────────────────────┐
│ bool HasValue (1 Byte)  │   int Value (4 Bytes)   │ + 3 Bytes Alignment Padding
└─────────────────────────┴─────────────────────────┘

Nullable Reference Type (string?):
Standard 8-Byte Pointer + Compiler Metadata Attribute ([Nullable(2)])

3Code Example

C# 13 & .NET 9
using System;

public class NullableComparisonDemo
{
    public static void Main()
    {
        int? nullableInt = null;
        Console.WriteLine($"Nullable Value Type HasValue: {nullableInt.HasValue}");

        nullableInt = 42;
        Console.WriteLine($"Value: {nullableInt.GetValueOrDefault(-1)}");

        string? nullableString = null; // Roslyn checks at compile time
        Console.WriteLine($"NRT String Length: {nullableString?.Length ?? 0}");
    }
}

4Expected Output

Nullable Value Type HasValue: False
Value: 42
NRT String Length: 0

5Key Takeaways

  • `int?` adds storage size and padding overhead.
  • Nullable Reference Types generate no runtime memory overhead.
  • Use the null-forgiving operator (`!`) only when you have guaranteed invariants outside compiler visibility.