.NET Academy

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);   // 💥 NullReferenceException

NullReferenceException 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 null

int? 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:

  • string means "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 spaces

Null operators

OperatorNameMeaning
a?.Bnull-conditionalnull if a is null, otherwise a.B
a?[i]null-conditional indexnull if a is null, otherwise a[i]
a ?? bnull-coalescinga if not null, otherwise b
a ??= bnull-coalescing assignmentassign 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 initialization

Use ! 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 them required:
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 ??:

Program.cs
Loading editor…

C# runtime not loaded

Key takeaways

  • Dereferencing null throws NullReferenceException.
  • int? lets value types be null; check .HasValue or 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.

Program.cs
Loading editor…

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 pass
  1. 1.What does `customer?.Name` evaluate to when customer is null?

  2. 2.What is `input ?? "default"` when input is "hello"?

  3. 3.Can a variable of type `int` hold null?

  4. 4.With nullable reference types enabled, what does `string?` mean?

To complete this lesson

  • ○ Solve the exercise
  • ○ Pass the quiz (3/4 correct)