Nullable Reference Types (NRT) sind ein mit C# 8 (2019) eingeführtes opt-in-Sprachfeature, das das jahrzehntealte Problem der NullReferenceException strukturell adressiert. Mit aktivierten NRTs unterscheidet das Typsystem zwischen nicht-nullbaren Referenztypen (string) und explizit nullbaren Referenztypen (string?). Der Compiler verfolgt mittels Flussanalyse, ob ein Wert an einer Stelle null sein kann, und gibt Warnungen aus, wenn Annahmen verletzt werden.
Eingesetzt wird das Feature pro Projekt oder pro Datei über Nullable=enable bzw. die Direktive #nullable enable. In Bibliothekscode signalisieren Annotationen wie [NotNull], [MaybeNull], [DisallowNull], [AllowNull] und [MemberNotNull] dem Compiler zusätzliche Garantien, die durch reine Typsignaturen nicht ausdrückbar sind. Praktisch wird NRT in modernen API-Designs, in Domänenmodellen, in Validierungslogik und in nahezu allen neuen Bibliotheken seit .NET 6 eingesetzt; Microsoft hat die eigenen Frameworks vollständig annotiert.
Der Einsatzzweck und das gelöste Problem ergeben sich aus dem berühmten ‚billion-dollar mistake'. Tony Hoare bezeichnete die Einführung von null in ALGOL W (1965) selbst als seinen ‚billion-dollar mistake', weil null-Referenzen seither weltweit unzählige Sicherheits- und Stabilitätsfehler verursacht haben. NRTs verschieben das Thema vom Laufzeit- in den Compile-Zeit-Bereich: Statt den Stack-Trace einer NullReferenceException in Produktion zu sehen, sieht der Entwickler eine Warnung im Editor.
Historisch ist NRT in einer Reihe akademischer und industrieller Bemühungen verortet, Nullsicherheit auf Typebene auszudrücken (Kotlin-Optionals, Swift-Optionals, Eiffel ‚void-safety', F#-Option-Typ). C# 8 bringt diese Idee als opt-in-Variante in eine Sprache mit großem Bestandscode, ohne Brechen der Binärkompatibilität. Spätere Versionen haben den Code-Flow-Analyzer kontinuierlich verfeinert und das Verhalten in Generics, Pattern Matching und LINQ verbessert.
Auf der Microsoft Build 2018 sagte Mads Torgersen sinngemäß, NRTs seien das ‚schwierigste Feature seit Generics', weil Microsoft das Spannungsfeld aushalten musste, einerseits eine massive Verbesserung der Codequalität anzubieten, andererseits Tausende existierender Bibliotheken nicht über Nacht zu zerstören. Die Lösung — Warnungen statt Fehler, opt-in pro Projekt — ist deshalb ein bewusster Kompromiss zwischen Sicherheit und Migrationsfreundlichkeit.
Bei bluehands gibt es die Regel, dass wir in jedem neuen Projekt und möglichst im Bestand, die Warnung als Fehler ausgeben. In Migrations-Szenarien verwenden wir als Alternative Option<T>, welches semantisch die gleiche Funktion bietet.