Nullable Reference Types

C# / .NET Interview Notes


1. Big Picture

Before C# 8.0, reference types were implicitly nullable — any string could be null, and the compiler said nothing. This caused billions of NullReferenceExceptions. Nullable Reference Types (NRT) make nullability explicit at compile time.

⭐ Quick Memory Trick:
string → "I will never be null" (compiler enforces)
string? → "I might be null" (you must check)
string! → "Trust me, not null" (suppress warning)

2. Enabling NRT

In .csproj:

<PropertyGroup>
  <Nullable>enable</Nullable>
  <LangVersion>latest</LangVersion>
</PropertyGroup>

Or per-file: #nullable enable


3. Nullable vs Non-Nullable

string name = "Alice";     // non-nullable — compiler guarantees not null
string? nickname = null;   // nullable — must check before use

// nickname.ToUpper();     // WARNING: may be null
if (nickname != null)
{
    Console.WriteLine(nickname.ToUpper());  // safe
}

4. Null-Forgiving Operator (!)

Suppress the warning when you know better than the compiler:

string? input = GetInput();
string result = input!;  // "trust me, it's not null"

// Dangerous if you're wrong — NullReferenceException at runtime
⚠️ Warning: ! suppresses the compiler warning but provides no runtime safety. Use sparingly.

5. Null-Coalescing Operators

?? — provide a default if null:

string? name = null;
string display = name ?? "Anonymous";  // "Anonymous"

// ??= — assign if null
name ??= "Default";

// ?. — null-conditional
int? length = name?.Length;  // null if name is null

6. Flow Analysis

The compiler tracks null state through your code:

void Process(string? input)
{
    if (input == null) return;
    // Here, compiler knows input is NOT null
    Console.WriteLine(input.Length);  // no warning

    input = null;
    // Now compiler warns again
    // Console.WriteLine(input.Length);  // WARNING
}

7. Nullable Value Types

Value types can also be nullable with ?:

int? age = null;      // nullable int
bool? isActive = null; // nullable bool

int actual = age ?? 0;  // unwrap with default
if (age.HasValue) { Console.WriteLine(age.Value); }

8. Common Patterns

Guard Clause

void Save(User? user)
{
    if (user is null) throw new ArgumentNullException(nameof(user));
    // user is now non-null for the rest of the method
    _db.Save(user);
}

Early Return

string FormatName(Person? person)
{
    if (person is null) return "Unknown";
    return $"{person.FirstName} {person.LastName}";
}

Pattern Matching with Null

if (input is not null && input.Length > 0)
{
    // safe to use input
}

9. Common Interview Questions

Q: What is the difference between string and string??

With NRT enabled, string is non-nullable (compiler enforces), string? is nullable (must check). Without NRT, both behave the same at runtime.

Q: Does NRT add runtime overhead?

No — it's purely a compile-time feature. The compiled IL is identical. It's a development-time safety net.

Q: What is the ! operator for?

Null-forgiving — tells the compiler "I know this isn't null, stop warning." Use when you have external knowledge the compiler lacks.


10. One-Line Interview Answer

Nullable Reference Types (C# 8+) make reference type nullability explicit at compile time — string is non-null, string? is nullable — eliminating unexpected NullReferenceExceptions through compiler warnings and flow analysis, with zero runtime overhead.