CodeOath
← All posts
C#65 min total · 17 parts

C# Fundamentals: Value Types, Reference Types, Boxing, and the Type System

Contents — Part 12 of 17: Nullable Value Types
Part 12 of 17 · ~1 min

Nullable Value Types

Value types normally can't be nullint x = null; doesn't compile. Nullable<T> (written as T?) adds that capability back for specific cases where "no value" is a real, distinct state from any actual value:

int? maybeAge = null;
if (maybeAge.HasValue) {
    Console.WriteLine(maybeAge.Value);
} else {
    Console.WriteLine("Unknown");
}

// The null-coalescing operator is the common idiomatic shorthand for "or a default"
int age = maybeAge ?? 0;

Under the hood, int? is a real struct — Nullable<int>, with exactly two fields: the wrapped value, and a bool flag for whether it's actually present. Calling .Value when HasValue is false throws an InvalidOperationException at runtime — a genuinely common bug when a nullable value is dereferenced without checking it first, functionally equivalent to a null-reference exception but on a value type.

This is distinct from nullable reference types (string? with <Nullable>enable</Nullable> turned on in the project file), which is a compile-time-only annotation and analysis feature that helps the compiler warn about potential null-reference bugs on reference types — it doesn't change runtime behavior the way Nullable<T> does for value types, and a string? that's actually null at runtime doesn't throw anything by itself until something tries to dereference it.