How to use nullable reference types in C#

Nullable reference types, introduced in C# 8.0, help prevent null reference exceptions by making nullability explicit. Enable them with <Nullable>enable</Nullable> in your project file or #nullable enable in code.

A type followed by ? (like string?) indicates it can be null. Types without ? should never be null, and the compiler warns you about potential null dereferences.

The null-forgiving operator ! tells the compiler you know a value isn't null, suppressing warnings. Use it sparingly when you have information the compiler doesn't.

C# Example Code
#nullable enable
using System;

        // Non-nullable reference type (cannot be null)
        string name = "Alice";
        Console.WriteLine($"Length: {name.Length}");  // Safe

        // Nullable reference type (can be null)
        string? nullableName = null;
        // Console.WriteLine(nullableName.Length);  // Warning: possible null reference

        // Safe null checking
        if (nullableName != null)
        {
            Console.WriteLine($"Length: {nullableName.Length}");
        }

        // Null-conditional operator
        int? length = nullableName?.Length;
        Console.WriteLine($"Length: {length ?? 0}");

        // Null-forgiving operator (use carefully!)
        string? possiblyNull = GetValue();
        string definitelyNotNull = possiblyNull!;  // Tells compiler it's not null
        Console.WriteLine(definitelyNotNull);

        // Method with nullable parameters
        PrintMessage(null);  // OK, parameter is nullable
        PrintMessage("Hello");

        // Method with non-nullable parameter
        // PrintRequired(null);  // Warning: passing null to non-nullable parameter
        PrintRequired("Required");

static string? GetValue()
{
    return "Some value";
}

static void PrintMessage(string? message)
{
    // Safe handling of nullable parameter
    Console.WriteLine(message ?? "No message");
}

static void PrintRequired(string message)
{
    // message is guaranteed to not be null (by contract)
    Console.WriteLine($"Required: {message.ToUpper()}");
}

// Properties with nullable reference types
class Person
{
    public string Name { get; set; } = "";  // Non-nullable, must initialize
    public string? MiddleName { get; set; }  // Nullable, can be null
    public string LastName { get; set; } = "";

    public string GetFullName()
    {
        return MiddleName != null
            ? $"{Name} {MiddleName} {LastName}"
            : $"{Name} {LastName}";
    }
}