Nullable in C#: Was der .NET-Experte empfiehlt – und warum das im Mittelstand anders landet

Maarten Balliauw erklärt fünf Wege, Nullable-Warnings bei JSON-Deserialisierung loszuwerden. Ich zeige, welche davon in einem KMU mit 30 Entwicklern überhaupt realistisch sind – und welche Voraussetzung du erfüllen musst, bevor du die beste Option überhaupt nutzen kannst.

⚙ KI-Entwurf Dieser Beitrag wurde automatisiert generiert und nicht redaktionell freigegeben. Behandelt ihn entsprechend.

Letztes Jahr, Mandat bei einem Softwarehaus mit etwa 80 Mitarbeitenden. Die haben ein internes ERP-System auf .NET 6 – solid, läuft, kein Grund zur Beschwerde. Dann kommt ein neuer Entwickler aus einem Großkonzern, fängt an, nullable reference types einzuschalten, und drei Wochen später landet eine E-Mail bei mir: „Wir haben plötzlich 400 Compiler-Warnings und keine Ahnung, wo wir anfangen sollen."

Das ist der Moment, wo der Unterschied zwischen theoretisch richtiger Empfehlung und praktisch umsetzbarer Empfehlung sichtbar wird. Nicht weil der neue Entwickler falsch lag – er lag völlig richtig. Sondern weil ein Team von fünf .NET-Entwicklern, die nebenbei noch SQL-Abfragen optimieren und die Jenkins-Pipeline am Leben halten müssen, eine andere Bandbreite hat als ein Enterprise-Team mit eigenem Code-Quality-Guild.

Was Maarten Balliauw sagt

Maarten Balliauw – bekannter Name in der .NET-Welt – hat in seinem Artikel fünf Optionen zusammengetragen, wie man mit der häufigsten Nullable-Warning bei JSON-Deserialisierung umgeht: Eigenschaft als nullable deklarieren, default! setzen (ausdrücklich nicht empfohlen), einen Primary Constructor nutzen (für Newtonsoft.Json), Default-Werte vergeben oder ab C# 11 das required-Schlüsselwort einsetzen. Letzteres ist seine klare Empfehlung, weil es semantisch sauber ist: Der Compiler weiß, dass die Eigenschaft immer initialisiert sein muss, und meckert, wenn sie es nicht ist. Was im Artikel nur als Fußnote steht, ist die entscheidende Einschränkung: required ist ein Compile-Time-Construct – zur Laufzeit hält es dir keine kaputten JSON-Payloads vom Hals.

Wie das im Mittelstand wirklich landet

Ich übersetze das jetzt in die Wirklichkeit eines Betriebs mit 15 bis 60 .NET-Entwicklern.

Erstens: Die meisten KMU-Projekte haben Nullable noch nicht aktiviert.

Das ist nicht Faulheit, das ist Ressourcenplanung. Nullable reference types gibt es als Feature seit C# 8 (2019), aber wer ein Legacy-System aus .NET-Framework-Zeiten auf .NET 6 oder 8 gehoben hat, der hat diesen Schalter bewusst ausgelassen. Zu viel Rauschen, zu wenig Zeit.

Was bedeutet das für Maartens Empfehlungen? Option 5 – required – setzt C# 11 voraus. C# 11 kommt mit .NET 7. Wer noch auf .NET 6 LTS sitzt, und das sind im Mittelstand noch verdammt viele, der kann diese Option schlicht nicht nutzen. Das steht nicht prominent im Artikel, weil Maartens Zielgruppe wahrscheinlich auf dem aktuellen Stack unterwegs ist. Für dich ist es relevant.

Zweitens: default! ist ein reales Problem, nicht nur ein akademisches.

Ich habe in vier Jahren KMU-Beratung mindestens acht Mal diese Zeile gesehen:

public string Name { get; set; } = default!;

Meistens kam sie rein, weil jemand die Warning wegklicken wollte – und weil der nächste PR-Reviewer entweder nichts davon wusste oder keine Zeit hatte. Dann fliegt drei Monate später eine NullReferenceException in Produktion, und niemand versteht warum, weil der Compiler ja grün war.

Maarten sagt „please don't" dazu. Ich sage: Schreib das explizit in deinen Code-Review-Checklist. Nicht als Nice-to-have. Als Blocker. Der Schaden eines einzigen unkontrollierten Null-Crashes in einem business-kritischen Prozess übersteigt den Aufwand für ein ordentliches DTO-Design um Faktor 10.

Drittens: Der Primary Constructor ist die unterschätzte Option.

Maartens Option 3 – den Konstruktor nutzen, damit Newtonsoft.Json den richtigen Pfad geht – klingt nach mehr Boilerplate. Stimmt. Aber es ist die Option, die am explizitesten ausdrückt, was passiert, wenn ein Feld fehlt: entweder ein sinnvoller Default oder eine Exception mit einer lesbaren Message.

In einem System, wo Drittanbieter-APIs angebunden sind – und das ist bei jedem zweiten meiner Mandate der Fall – ist das Gold wert. Externe APIs sind die Hauptquelle für „JSON enthält plötzlich nicht mehr das, was wir erwartet haben". Mit einem Konstruktor weißt du sofort, welches Feld fehlt und warum. Mit required weißt du es erst zur Laufzeit, wenn die Exception keine Zusatzinfo liefert.

Was im Artikel fehlt: die Migrations-Frage.

Maartens Artikel setzt voraus, dass du Nullable schon aktiviert hast und jetzt eine saubere Lösung für deine DTOs suchst. Für viele KMU ist der eigentliche Schmerz ein anderer: Wie aktiviere ich Nullable in einem bestehenden Projekt mit 300 Klassen, ohne drei Wochen Vollbeschäftigung dafür aufzuwenden?

Die kurze Antwort: stufenweise. #nullable enable pro Datei, nicht auf Projektebene. Fang mit den neuen DTOs an, lass die alten in Ruhe, bis du sie ohnehin anfasst. Das ist nicht elegant, aber es ist machbar für ein Team, das auch noch Features liefern muss.

Konkrete Empfehlung nach Situation

Was ich heute in KMU-Projekten empfehle:

  • Neues Projekt, .NET 8+, System.Text.Json: required für alle DTOs aus externen Quellen. Kombiniert mit einem try-catch und Logging an der Deserialisierungsgrenze – nicht im DTO selbst, sondern im Service.
  • Bestehendes Projekt, Newtonsoft.Json, gemischte .NET-Version: Konstruktor-Ansatz für alle neuen oder überarbeiteten DTOs. Kein default!. Kein string? ohne echten Grund.
  • Legacy-Projekt, noch kein Nullable aktiviert: Erst nichts ändern. Wenn du eine Klasse anfasst, aktiviere Nullable für diese Datei und mach den Primary Constructor direkt mit. So baust du schrittweise Qualität auf, ohne das Team zu überlasten.

Was ich in keinem dieser Szenarien empfehle: den = default!-Workaround. Nicht mal als temporäres TODO. Er bleibt nämlich – das weiß jeder, der mal ein Projekt geerbt hat.


Der vollständige Original-Beitrag von Maarten Balliauw: Getting rid of warnings with nullable reference types and JSON object models in C#

Wenn du gerade ein .NET-Projekt erbst und nicht weißt, ob du jetzt Nullable aktivieren, erst mal alles mit default! zuschmeißen oder lieber gar nichts anfassen sollst: Lass uns das in 30 Minuten durchgehen.

30 Min Klartext-Sparring

— Bernhard