Nullable Reference Types
Null Safety
Introduction
In this lesson, you'll learn about nullable reference types in C#. Coming from TypeScript, you already have a foundation for understanding this concept. We'll build on that knowledge while highlighting the key differences.
In TypeScript, you're familiar with null safety.
C# has its own approach to null safety, which we'll explore step by step.
The C# Way
Let's see how C# handles this concept. Here's a typical example:
// C# 8+ nullable reference types (#nullable enable)
#nullable enable
int GetLength(string? s) {
return s?.Length ?? 0;
}
class Config {
public string Host { get; set; } = "";
public int? Port { get; set; } // nullable int
}
void Connect(Config config) {
int port = config.Port ?? 3000;
}Comparing to TypeScript
Here's how you might have written similar code in TypeScript:
// TypeScript strict mode — null safety enforced by compiler
function getLength(s: string | null): number {
return s?.length ?? 0;
}
interface Config {
host: string;
port?: number; // optional = string | undefined
}
function connect(config: Config) {
const port = config.port ?? 3000;
}You may be used to different syntax or behavior.
C# nullable reference types require #nullable enable (or project-wide setting)
You may be used to different syntax or behavior.
string? in C# means nullable, exactly like string | null in TypeScript strict mode
You may be used to different syntax or behavior.
?. optional chaining and ?? nullish coalescing work identically in C#
You may be used to different syntax or behavior.
Value types (int, bool) use int? (Nullable<int>) to allow null
Step-by-Step Breakdown
1. Enabling Nullable Context
C# nullable reference types are opt-in per file (#nullable enable) or project-wide (via .csproj). Without it, all references can be null silently.
// TypeScript: enable via tsconfig { "strict": true }// Per file:
#nullable enable
// Or in .csproj:
<Nullable>enable</Nullable>2. string? — Nullable Reference
In nullable context, string is non-nullable (must always have a value) and string? is nullable. This mirrors TypeScript's string vs string | null.
let name: string = "Alice"; // non-nullable
let maybe: string | null = null; // nullablestring name = "Alice"; // non-nullable
string? maybe = null; // nullable3. ?. and ?? Work Identically
Optional chaining (?.) and nullish coalescing (??) have identical syntax and semantics in C# and TypeScript. Anders designed both.
const city = user?.address?.city ?? "Unknown";string city = user?.Address?.City ?? "Unknown";4. Nullable Value Types: int?
TypeScript numbers are always reference-like. C# distinguishes value types (int, bool, double) from reference types. Use int? (Nullable<int>) to allow null for value types.
let count: number | null = null;int? count = null;
if (count.HasValue) {
Console.WriteLine(count.Value);
}
// or:
int actual = count ?? 0;Common Mistakes
When coming from TypeScript, developers often make these mistakes:
- C# nullable reference types require #nullable enable (or project-wide setting)
- string? in C# means nullable, exactly like string | null in TypeScript strict mode
- ?. optional chaining and ?? nullish coalescing work identically in C#
Key Takeaways
- Enable #nullable in C# — equivalent to strict: true in tsconfig
- string? in C# nullable context maps exactly to string | null in TypeScript
- ?. and ?? work identically in both C# and TypeScript
- Value types (int, double) need int? syntax for nullable — reference types just use T?