null and nullable types
Handle missing values safely with nullable types, ?., ?? and the compiler's null-safety warnings.
11 min read
You will learn
- Explain what null means and why it causes crashes
- Use nullable value types like int?
- Use ?. , ?? and ??= to handle null concisely
- Read and fix nullable reference type warnings
The billion-dollar mistake
A reference-type variable can contain null — a reference to nothing. Using a member of null crashes:
string? name = null;
Console.WriteLine(name.Length); // 💥 NullReferenceExceptionNullReferenceException is the most common exception in .NET. The inventor of null references, Tony Hoare, called them his "billion-dollar mistake". C# gives you several tools to stay safe.
Nullable value types: int?
Value types can't be null — an int always holds a number. When "no value" is meaningful (a score not entered yet, an optional age), use a nullable value type by adding ?:
int? age = null;
if (age.HasValue)
Console.WriteLine($"Age: {age.Value}");
else
Console.WriteLine("Age unknown");
age = 36;
int realAge = age ?? 0; // fall back to 0 if nullint? is shorthand for Nullable<int>.
Nullable reference types
Modern projects enable nullable reference types (<Nullable>enable</Nullable> in the .csproj, on by default in new projects and in this course's editor). The compiler then tracks which references may be null:
stringmeans "should never be null".string?means "might be null — check before use".
string? GetMiddleName() => null;
string? middle = GetMiddleName();
Console.WriteLine(middle.Length);
// ~~~~~~ warning CS8602: Dereference of a possibly null reference.These are warnings, not errors: the program still compiles. But each one marks a potential crash — treat them seriously.
Note
Nullable reference types are purely a compile-time feature. At run time string? and string are the same type; nothing stops a null from arriving from old code. The annotations help the compiler help you.
Checking for null
if (middle is not null)
{
Console.WriteLine(middle.Length); // no warning: the compiler knows it's not null here
}
if (string.IsNullOrEmpty(middle)) { ... } // null or ""
if (string.IsNullOrWhiteSpace(middle)) { ... } // null, "" or only spacesNull operators
| Operator | Name | Meaning |
|---|---|---|
a?.B | null-conditional | null if a is null, otherwise a.B |
a?[i] | null-conditional index | null if a is null, otherwise a[i] |
a ?? b | null-coalescing | a if not null, otherwise b |
a ??= b | null-coalescing assignment | assign b to a only if a is null |
a! | null-forgiving | "trust me, it's not null" — silences the warning |
They combine beautifully:
string city = order?.Customer?.Address?.City ?? "Unknown";
int length = name?.Length ?? 0;
cache ??= LoadCache(); // lazy initializationUse ! sparingly
name!.Length removes the warning but not the danger. Only use ! when you know something the compiler can't — and prefer restructuring the code so it can tell.
Designing with null
- Make values non-nullable by default; add
?only where "missing" is a real possibility. - Initialize properties:
public string Name { get; set; } = "";or make themrequired:
class User
{
public required string Email { get; init; } // must be set in the object initializer
public string? Nickname { get; init; } // genuinely optional
}
var u = new User { Email = "ada@example.com" };- Return an empty collection, not
null, when there's nothing to return.
Try it
Read the warnings under the output, then fix them with ?. and ??:
C# runtime not loaded
Key takeaways
- Dereferencing
nullthrowsNullReferenceException. int?lets value types be null; check.HasValueor use??.- With nullable reference types,
string?may be null and the compiler warns about unsafe use. ?.,??and??=handle missing values concisely; avoid overusing!.
Exercise
Make these methods null-safe. Greet returns "Hello, guest!" when the name is null or only whitespace. NameLength returns 0 for null. City returns the customer's city, or "Unknown" if the customer, their address or the city is missing.
C# runtime not loaded
Hint 1
The compiler is already warning you (CS8602, "dereference of a possibly null reference") on exactly the lines that crash.
Hint 2
string.IsNullOrWhiteSpace(name) checks for null, empty and whitespace in one go.
Hint 3
Chain ?. and finish with ??: customer?.Address?.City ?? "Unknown".
Show solution
Console.WriteLine(Greet("Ada"));
Console.WriteLine(NameLength("Ada"));
Console.WriteLine(City(new Customer { Address = new Address { City = "Paris" } }));
string Greet(string? name) =>
string.IsNullOrWhiteSpace(name) ? "Hello, guest!" : $"Hello, {name}!";
int NameLength(string? name) => name?.Length ?? 0;
string City(Customer? customer) => customer?.Address?.City ?? "Unknown";
class Customer
{
public Address? Address { get; set; }
}
class Address
{
public string? City { get; set; }
}Quiz
4 questions · 3 correct to pass1.What does `customer?.Name` evaluate to when customer is null?
2.What is `input ?? "default"` when input is "hello"?
3.Can a variable of type `int` hold null?
4.With nullable reference types enabled, what does `string?` mean?
To complete this lesson
- ○ Solve the exercise
- ○ Pass the quiz (3/4 correct)