Enable C# nullable reference types (NRTs) in an existing codebase. This is a summary of the standard NRT migration process.
Add <Nullable>enable</Nullable> to the <PropertyGroup> in your .csproj. Remove any <NoWarn> for nullable warnings. Build with dotnet build --no-incremental to get all warnings.
| Warning | Meaning | Typical Fix |
|---|---|---|
| CS8602 | Dereference of a possibly null reference | Make the type nullable (T?) if null is valid, or use ! if provably non-null |
| CS8600 | Converting possible null to non-nullable type | Add ? to the target type, or ! if provably non-null |
| CS8603 | Possible null reference return | Change return type to T? if the method can return null |
| CS8604 | Possible null reference argument | Mark the parameter as nullable if null is valid |
| CS8618 | Non-nullable field not initialized in constructor | Initialize the member, make it nullable, or use required (C# 11+) |
| CS8601 | Possible null reference assignment | Same as CS8600 |
| CS8625 | Cannot convert null literal to non-nullable type | Make the target nullable or provide a non-null value |
When ? alone cannot express the null contract, use attributes from System.Diagnostics.CodeAnalysis:
| Attribute | Use when |
|---|---|
[NotNullWhen(true/false)] |
A bool-returning method guarantees a parameter is non-null when it returns a specific value |
[MaybeNullWhen(true/false)] |
An out parameter may be null when the method returns a specific value |
[NotNull] |
A nullable parameter is guaranteed non-null after the method returns |
[MemberNotNull(nameof(field))] |
A method guarantees a field/property is non-null after it returns |
[MemberNotNullWhen(true, nameof(field))] |
A bool-returning method guarantees a field is non-null when it returns a specific value |
[AllowNull] |
A non-nullable property/parameter should accept null (e.g., setter normalizes null to default) |
[DisallowNull] |
A nullable property/parameter should not accept null |
[MaybeNull] |
A non-nullable return/out may be null (useful for unconstrained generics) |
[DoesNotReturn] |
A method never returns (throws unconditionally) |
- Enable
<Nullable>enable</Nullable>in the csproj - Do a clean build (
dotnet build --no-incremental) - Fix dereference warnings (CS8602, CS8600, CS8603, CS8604)
- Fix declaration warnings (CS8618, CS8625, CS8601)
- Apply nullable attributes for advanced scenarios
- Validate: zero warnings, tests pass
After completing, add <WarningsAsErrors>nullable</WarningsAsErrors> to prevent regressions.
T= non-nullable (promise: never null).T?= nullable (may be null).- For reference types,
?is metadata-only — no runtime effect. - For value types (int, enum, struct),
?changes toNullable<T>— runtime effect. !(null-forgiving operator) suppresses warnings — metadata-only, no runtime effect.Debug.Assert(x != null)acts as a compiler hint for flow analysis.