Nullable Reference Types

V10 enables nullable reference types across all Brighter projects, providing improved type safety and helping prevent null reference exceptions.


Understanding Nullable Reference Types

Non-Nullable by Default

In C# with nullable reference types enabled, reference types are non-nullable by default:

// This string cannot be null
string name = "John";

// Compiler warning: Cannot convert null to non-nullable reference type
string name = null; // ⚠️ CS8600

Nullable Types

Use ? to explicitly mark types as nullable:

// This string can be null
string? optionalName = null; // ✅ OK

// Must check for null before using
if (optionalName != null)
{
    Console.WriteLine(optionalName.Length);
}

Impact on Brighter Code

Commands and Events

Required properties should be non-nullable:

Handlers

Handler dependencies should declare nullability appropriately:

Message Mappers

Message mappers should handle nullable message properties:


V10 Changes

BREAKING CHANGE: Nullable reference types are now enabled across all Brighter projects. You may need to update your code to address compiler warnings.

What Changed

  • All Brighter projects now have <Nullable>enable</Nullable> in their project files

  • Required properties are now non-nullable by default

  • Optional properties are explicitly marked as nullable with ?

  • Compiler warnings (CS8600-CS8629) will appear for potential null reference issues

Benefits

  1. Compile-Time Safety: Catch potential null reference issues before runtime

  2. Clear Intent: Explicitly declare which properties can be null

  3. Better Documentation: API signatures clearly show nullability expectations

  4. Reduced Runtime Errors: Fewer NullReferenceException errors in production


Migration Guide

Step 1: Enable Nullable Reference Types

If you haven't already, enable nullable reference types in your project:

Step 2: Address Compiler Warnings

After enabling nullable reference types, you'll see compiler warnings. Address them systematically:

CS8600: Converting null literal or possible null value to non-nullable type

Problem:

Solutions:

Option 1: Make the type nullable:

Option 2: Provide a non-null value:

CS8601: Possible null reference assignment

Problem:

Solutions:

Option 1: Make property nullable if it can be null:

Option 2: Initialize with a default value:

Option 3: Use required keyword (C# 11+):

CS8602: Dereference of a possibly null reference

Problem:

Solutions:

Option 1: Null check:

Option 2: Null-conditional operator:

Option 3: Null-coalescing operator:

Option 4: Null-forgiving operator (use cautiously):

CS8603: Possible null reference return

Problem:

Solutions:

Option 1: Make return type nullable:

Option 2: Return a non-null value:

CS8618: Non-nullable field must contain a non-null value when exiting constructor

Problem:

Solutions:

Option 1: Initialize in constructor:

Option 2: Initialize with default value:

Option 3: Make nullable if appropriate:

Option 4: Use required keyword (C# 11+):

Step 3: Update Handler Code

Review your handlers for null safety:

Step 4: Update Message Mappers

Ensure message mappers handle deserialization nullability:


Best Practices

1. Use Non-Nullable for Required Properties

Make your intent clear by using non-nullable types for properties that should never be null:

2. Validate at Boundaries

Validate nullability at system boundaries (message mappers, API controllers):

3. Use Null-Coalescing for Defaults

Use ?? operator to provide sensible defaults:

4. Document Nullability in XML Comments

Make nullability expectations explicit in documentation:

5. Avoid Null-Forgiving Operator Unless Certain

Use the null-forgiving operator (!) sparingly:

6. Use Pattern Matching for Null Checks

Modern C# pattern matching provides concise null checks:

7. Consider Required Members (C# 11+)

Use required keyword for properties that must be initialized:


Common Patterns in Brighter

Command with Validation

Event with Optional Properties

Handler with Optional Dependencies


Troubleshooting

Warning: Treat as Errors

Some teams treat warnings as errors. If you're seeing build failures:

You must address all nullable warnings before the build succeeds.

If you must temporarily suppress warnings (not recommended for production code):

Gradual Migration

For large codebases, consider enabling nullable reference types gradually:

Then address warnings incrementally and eventually enable TreatWarningsAsErrors.


Additional Resources

Last updated

Was this helpful?