Null and nullable types

C# · Essentials · 12 min

NullReferenceException is the classic .NET crash; the compiler's null analysis prevents most of them.

Value types like int can never be null; int? (short for Nullable<int>) adds a null state, with HasValue and Value, or GetValueOrDefault().

Reference types (classes, strings, arrays) can be null at runtime. With nullable reference types enabled (<Nullable>enable</Nullable>, the default in new projects), the compiler tracks nullability:

  • string means "should never be null"; assigning null gives a warning.
  • string? means "may be null"; dereferencing it without a check gives a warning.

The compiler does flow analysis: after if (name is null) return; it knows name is non-null. These are warnings, not runtime checks, so treat them seriously (or enable warnings as errors).

Operators for working with null:

  • a?.B returns null instead of throwing if a is null; a?[0] for indexers.
  • x ?? fallback uses the fallback when x is null; x ??= value assigns only if null.
  • x is null / x is not null are the clearest checks (they can't be overloaded).
  • x! (null-forgiving) tells the compiler "trust me"; overuse defeats the feature.

ArgumentNullException.ThrowIfNull(arg) validates public method arguments. C# 14 also allows null-conditional assignment: customer?.Order = order; only assigns when customer is non-null.

Example

int? maybeAge = null;
Console.WriteLine(maybeAge.HasValue);           // False
Console.WriteLine(maybeAge ?? -1);              // -1

string? FindUser(int id) => id == 1 ? "Ada" : null;

string? user = FindUser(2);
Console.WriteLine(user?.Length);                // (empty line: null)
Console.WriteLine(user?.Length ?? 0);           // 0

user ??= "guest";
Console.WriteLine(user.ToUpper());              // GUEST

static int Len(string? s)
{
    if (s is null) return 0;
    return s.Length;          // compiler knows s is not null here
}
Console.WriteLine(Len(FindUser(1)));            // 3

Remember

  • int? adds null to value types
  • With nullable reference types on, string? may be null and string should not be
  • ?. and ?? replace most manual null checks
  • Use the ! operator rarely; fix the flow instead

Watch out for

  • Silencing every warning with ! instead of handling the null case.

Check yourself

  1. What is the type of s?.Length when s is a string?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: learn.microsoft.com/en-us/dotnet/csharp/nullable-references