What are nullable reference types in C# and why were they introduced?
Learn what nullable reference types are in C#, why they were introduced, and how they catch NullReferenceExceptions at compile time with zero runtime cost.
Expected Interview Answer
Nullable reference types are a C# 8 feature that lets you express whether a reference type is intended to hold null (string?) or not (string), so the compiler can warn you about potential null dereferences at compile time.
When the feature is enabled (via #nullable enable or the project's Nullable setting), the compiler performs static flow analysis and flags places where a non-nullable reference might be null or where a nullable value is dereferenced without a check. They were introduced to attack the single most common runtime crash in .NET — the NullReferenceException — by moving null-safety concerns from runtime to compile time. Crucially, they are compile-time annotations only: at runtime a string? is still just a string, so there is no boxing, wrapper, or performance cost.
- Catches null bugs at compile time instead of at runtime
- Documents intent — a signature says whether null is allowed
- Zero runtime cost; annotations are erased after compilation
- Opt-in and gradual — enable per file or per project
- Improves API clarity for callers and library consumers
AI Mentor Explanation
A team sheet where every batting slot must be filled counts as a non-nullable reference, while a marked 'optional twelfth man' slot is nullable. The match referee checking the sheet before play catches an empty required slot up front, just as the compiler flags a missing non-null value before the innings ever begins.
Step-by-Step Explanation
Step 1
Enable the feature
Set <Nullable>enable</Nullable> in the .csproj or add #nullable enable at the top of a file to turn on flow analysis.
Step 2
Annotate intent
Use string for values that must never be null and string? for values that are allowed to be null.
Step 3
Fix the warnings
The compiler flags dereferences of possibly-null values and assignments of null to non-nullable references; add null checks to resolve them.
Step 4
Use null-flow operators
Apply ?., ??, and the null-forgiving ! operator to guide or override the compiler's analysis where you know more than it does.
Step 5
Adopt gradually
Enable the feature file by file or project by project so a large codebase can migrate without a single massive change.
What Interviewer Expects
- Understanding it is a compile-time feature with zero runtime cost
- Knowing string? versus string and how warnings are produced
- Awareness of the null-forgiving ! operator and when to use it
- That the motivation is preventing NullReferenceException
- Knowing how to enable it via project settings or #nullable directives
Common Mistakes
- Believing string? changes the runtime type or adds a wrapper
- Overusing the null-forgiving ! operator to silence warnings instead of fixing them
- Thinking the feature enforces null-safety at runtime rather than at compile time
- Assuming enabling it is all-or-nothing rather than gradual
- Confusing nullable reference types with Nullable<T> for value types
Best Answer (HR Friendly)
“Nullable reference types are a C# feature that lets developers mark whether a variable is allowed to be empty (null) or not. The compiler then warns them early if they might accidentally use an empty value, which prevents one of the most common crashes in software.”
Code Example
#nullable enable
public class User
{
// Non-nullable: must always have a value
public string Name { get; set; } = string.Empty;
// Nullable: may legitimately be null
public string? MiddleName { get; set; }
}
void Print(User u)
{
// OK: Name is non-nullable
Console.WriteLine(u.Name.ToUpper());
// Warning: possible null dereference
// Console.WriteLine(u.MiddleName.ToUpper());
// Safe: guard first
if (u.MiddleName is not null)
Console.WriteLine(u.MiddleName.ToUpper());
}Follow-up Questions
- What does the null-forgiving operator (!) do and when is it appropriate?
- How do nullable reference types differ from Nullable<T> value types?
- What are nullable annotation contexts and how do you scope them?
- How do you migrate a large existing codebase to nullable reference types?
- What attributes like [NotNull] or [MaybeNull] help refine the analysis?
MCQ Practice
1. What is the runtime cost of declaring a variable as string? instead of string?
Nullable reference type annotations are compile-time only and are erased after compilation, so string? is just a string at runtime.
2. Which operator tells the compiler you know a value is not null despite its analysis?
The null-forgiving operator ! suppresses the compiler's nullability warning at that expression, asserting the value is non-null.
3. Why were nullable reference types introduced in C# 8?
They move null-safety concerns to compile time to catch the extremely common NullReferenceException before the program runs.
Flash Cards
What does string? mean in C#? — A reference that is explicitly allowed to be null; the compiler warns if you dereference it without a null check.
Do nullable reference types cost anything at runtime? — No. They are compile-time annotations only and are erased after compilation.
How do you enable nullable reference types? — Set <Nullable>enable</Nullable> in the .csproj or use #nullable enable in a file.
What does the ! operator do? — The null-forgiving operator suppresses a nullability warning, asserting the value is non-null.
What problem do nullable reference types target? — The NullReferenceException — the most common runtime crash in .NET — by catching it at compile time.