Are nullable types reference types?
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
Nullable types in C# solve a practical problem: value types like int and DateTime normally cannot represent missing data. That limitation becomes painful when reading from databases, external APIs, or partially completed forms. The short answer to the common question is that nullable value types are still value types, even though they can hold null.
Core Sections
Nullable value types in C#
A nullable value type is written as T?, where T is a value type. Under the hood, the compiler translates int? into Nullable<int>. This wrapper stores two things: the underlying value and a boolean that tells whether a value is present. That design keeps the type efficient while still supporting missing data.
In day to day code, nullable value types are often used in domain models and query filters. They also work well with operators such as null coalescing and pattern checks. The important point is that assignments, comparisons, and arithmetic can behave differently when a value is missing, so explicit handling is a good habit.
Why nullable value types are not reference types
Even with null support, int? does not become a reference type. It is still a struct with value semantics. You can see this with typeof, boxing behavior, and memory layout expectations. A reference type stores a reference to an object on the heap. A nullable value type stores data directly, unless it is boxed.
When boxing occurs, null nullable values box to null, and non null values box to the underlying value type instance. This behavior can surprise developers who expect every nullable value to box into a Nullable<T> object.
Nullable reference types are a different feature
Starting with newer C# versions, nullable reference types add compiler analysis for reference values. This feature is about warnings and intent, not a new runtime representation. string? means a string reference may be null, while string means it should not be null. The runtime type remains System.String in both cases.
Use both features together: nullable value types for optional numbers and dates, nullable reference annotations for optional object references. That combination improves correctness without overcomplicating model classes.
Common Pitfalls
- Assuming
int?is a reference type and expecting reference equality behavior. Fix this by treating it as a value type with nullable semantics. - Accessing
.Valuedirectly without checkingHasValue. Use pattern matching,??, orGetValueOrDefaultto avoid runtime errors. - Confusing nullable value types with nullable reference annotations. Keep in mind that one changes data representation and the other guides compiler analysis.
- Forgetting boxing rules when passing nullable values as
object. Test null and type behavior explicitly in interoperability code. - Disabling nullable context globally to suppress warnings. Instead, enable it and address warnings gradually to improve code health.
Summary
T?for value types in C# compiles toNullable<T>and remains a value type.- Nullable value types store value plus presence state, not a heap reference by default.
- Boxing nullable values has special behavior that differs for null and non null cases.
- Nullable reference types are compiler level nullability annotations for reference values.
- Combining both features leads to safer and clearer application models.

