Nullable Reference Types and Null-Conditional/Coalescing Operators
C#'s null-safety feature, plus the `?.` and `??` operators for working with possibly-null values.
What you'll learn
- Distinguish a nullable reference type (`string?`) from a non-nullable one (`string`)
- Use `?.` to safely access a member that might be null
- Use `??` to supply a fallback value when an expression is null
Explanation
In a modern C# project (with nullable reference types enabled, the default for new projects), the compiler tracks nullability as part of a reference type's type: string means "the compiler expects this is never null," while string? means "this may legitimately be null, and code that dereferences it without checking should get a compiler warning." This is purely a compile-time analysis to catch a common class of bug earlier -- it does not add runtime null checks by itself.
The null-conditional operator ?. accesses a member only if the value on its left isn't null, short-circuiting to null instead of throwing if it is: middleName?.Length is null if middleName is null, or the actual length otherwise -- without it, middleName.Length on a null middleName throws a NullReferenceException at run time.
The null-coalescing operator ?? supplies a fallback when the left side is null: nickname ?? "Unknown" evaluates to nickname if it isn't null, or the literal "Unknown" if it is. The two operators combine naturally: person?.Nickname ?? "Unknown" safely navigates a possibly-null person and still gives you a real value either way.
Inside a composite/interpolated string, a genuinely null value formats as an empty string, not the text "null" -- a subtlety worth knowing before you're surprised by a blank spot in printed output instead of an exception or the word "null".
Guided lab
Predict: Null-conditional and null-coalescing operators
Read this program and predict exactly what it prints.
using System;
string? middleName = null;
string? nickname = "Ace";
int? middleLength = middleName?.Length;
int? nicknameLength = nickname?.Length;
Console.WriteLine($"middleLength: {middleLength}");
Console.WriteLine($"nicknameLength: {nicknameLength}");
string displayName = nickname ?? "Unknown";
string displayMiddle = middleName ?? "(none)";
Console.WriteLine($"displayName: {displayName}");
Console.WriteLine($"displayMiddle: {displayMiddle}");Stuck? Get a hint.
Common mistakes
- Dereferencing a `string?` directly without `?.` or a null check, risking a `NullReferenceException` at run time that the compiler had already warned about.
- Assuming `??` and `?.` do the same thing -- `?.` safely navigates a member access, while `??` supplies a fallback value for an already-evaluated possibly-null expression.
- Expecting a null value inside an interpolated string to print the word "null" -- it actually formats as an empty string.
Knowledge check
Takeaway
Use `?.` to safely navigate a possibly-null reference and `??` to supply a fallback value -- and remember a null value inside an interpolated string formats as an empty string, not the word "null".
Summary
Nullable reference types (`string?`) let the compiler warn about unchecked null dereferences at compile time; `?.` safely navigates possibly-null members, `??` supplies a fallback, and null formats as an empty string in interpolation.
References
Your notes
Notes save automatically.
Finished this lesson?
Mark it complete to track your progress and schedule a future review.
AI tutor
The optional AI tutor isn't enabled in this deployment. All lessons, exercises, quizzes, and search work fully without it.