C# distinguishes types that can be from those that can't. () let value types hold null, (a compiler feature) help catch null bugs, and (, , ) make working with possibly-null values clean and safe — addressing the pervasive null-reference problem.
C# distinguishes types that can be from those that can't. () let value types hold null, (a compiler feature) help catch null bugs, and (, , ) make working with possibly-null values clean and safe — addressing the pervasive null-reference problem.
nullint??.??!int x = 5; // a value type — CANNOT be null
int? y = null; // int? = Nullable<int> — CAN be null
if (y.HasValue) { int val = y.Value; } // check + access
int z = y ?? 0; // default if null
Value types can't normally be null, but int? (Nullable<int>) allows it — common for optional/missing data (e.g. a nullable database column).
#nullable enable // (on by default in modern projects)
string name = null; // ⚠️ warning — string is non-nullable by default now
string? maybe = null; // ✅ string? explicitly allows null
void Use(string? s) {
Console.WriteLine(s.Length); // ⚠️ warning — s might be null (must check first)
}
With nullable reference types enabled, the compiler tracks which references can be null (string?) vs not (string) and warns when you might dereference null — catching NullReferenceException bugs at compile time. This is a major modern C# safety feature.
// ?. null-conditional — short-circuits to null instead of throwing
int? len = user?.Name?.Length; // null if user or Name is null (no exception)
user?.DoSomething(); // only calls if user isn't null
// ?? null-coalescing — provide a default
string name = input ?? "Anonymous";
name ??= "fallback"; // assign if currently null
// ! null-forgiving — assert non-null (suppress the warning; use carefully)
string definitelyNotNull = maybe!; // "I know it's not null" — no runtime check
The null-conditional operator (?.) safely accesses members of possibly-null values (returning null instead of throwing), and ?? provides defaults — together making null handling clean and safe.
Null handling is one of the most important aspects of writing robust C#, since NullReferenceException ("the billion-dollar mistake") is one of the most common runtime errors — and C#'s nullable types and operators directly address it, making them essential knowledge. Nullable value types (int?) are practically necessary for representing optional/missing data (nullable database fields, optional values).
The nullable reference types feature (now on by default in modern .NET projects) is a major safety improvement: by having the compiler track and warn about possible null dereferences, it catches a whole class of null bugs at compile time rather than as runtime crashes — a significant reliability benefit that you should understand and heed.
The null-handling operators are everyday tools that make working with possibly-null values clean and safe: the null-conditional operator (?.) safely navigates possibly-null chains (returning null instead of throwing), ??/??= provide defaults concisely, and ! asserts non-null (to be used carefully).
Understanding nullable value types, the nullable-reference-types safety feature, and the null-handling operators (?., ??, !) is important for writing null-safe, robust C# that avoids the pervasive NullReferenceException — a frequent, practically-critical concern.
Since null-related bugs are so common and C# provides strong tools (especially compile-time null checking) to prevent them, mastering nullable types and null operators is foundational, must-know knowledge for writing reliable modern C#.