Aktualisieren einer Codebasis mit Nullable-Verweistypen zur Verbesserung von NULL-Diagnosewarnungen

Nullable-Verweistypen ermöglichen es zu deklarieren, ob Variablen eines Verweistyps ein null-Wert zugewiesen werden soll oder nicht. Die statische Analyse des Compilers und Warnungen, wenn Ihr Code null dereferenzieren kann, sind der wichtigste Vorteil dieses Features. Wenn diese Funktion aktiviert ist, erzeugt der Compiler Warnungen, die Ihnen helfen, bei der Ausführung Ihres Codes ein Verwerfen von System.NullReferenceException zu vermeiden.

Wenn Ihre Codebasis relativ klein ist, können Sie das -Feature in Ihrem Projekt aktivieren, Warnungen bearbeiten und die Vorteile der verbesserten Diagnose nutzen. Größere Codebasen erfordern möglicherweise einen strukturierteren Ansatz, um im Laufe der Zeit angezeigte Warnungen zu bearbeiten, indem das Feature selektiv aktiviert wird, wenn Sie Warnungen in verschiedenen Typen oder Dateien bearbeiten. Dieser Artikel beschreibt verschiedene Strategien zur Aktualisierung einer Codebasis und die mit diesen Strategien verbundenen Kompromisse. Bevor Sie mit der Migration beginnen, lesen Sie den konzeptionellen Überblick über Nullable-Verweistypen. Er betrifft die statische Analyse des Compilers, die null-state-Werte von maybe-null und not-null sowie die Nullable-Anmerkungen. Sobald Sie mit diesen Konzepten und Begriffen vertraut sind, können Sie Ihren Code migrieren.

Planen Ihrer Migration

Unabhängig davon, wie Sie Ihre Codebasis aktualisieren, müssen Nullable-Warnungen und Nullable-Anmerkungen in Ihrem Projekt aktiviert werden. Sobald Sie dieses Ziel erreicht haben, haben Sie die <nullable>Enable</nullable>-Einstellung in Ihrem Projekt. Sie benötigen keine Präprozessordirektiven, um Einstellungen an anderer Stelle anzupassen.

Hinweis

Sie können eine Nullable-Einstellung mithilfe eines <Nullable>-Tags für Ihr Projekt bestimmen. Weitere Informationen finden Sie unter Compileroptionen.

Die beste Option ist die Definition der Standardeinstellungen für das Projekt. Folgende Optionen stehen zur Auswahl:

  1. Nullable als Standard deaktivieren: disable ist die Standardeinstellung, wenn Sie kein Nullable-Element zu Ihrer Projektdatei hinzufügen. Verwenden Sie diese Standardeinstellung, wenn Sie neue Dateien nicht aktiv zur Codebasis hinzufügen. Die Hauptaufgabe ist die Aktualisierung der Bibliothek, um Nullable-Verweistypen zu verwenden. Wenn Sie diese Standardeinstellung verwenden, fügen Sie jeder Datei eine Nullable-Präprozessordirektive hinzu, wenn Sie den Code aktualisieren.
  2. Nullable als Standard aktivieren: Legen Sie diese Standardeinstellung fest, wenn Sie aktiv neue Features entwickeln. Sie möchten Nullable-Verweistypen und statische Nullable-Analysen für den gesamten neuen Code nutzen. Wenn Sie diesen Standard verwenden, müssen Sie am Anfang jeder Datei ein #nullable disable hinzufügen. Sie entfernen diese Präprozessordirektiven, wenn Sie die Warnungen in den einzelnen Dateien behandeln.
  3. Nullable-Warnungen als Standardeinstellung: Wählen Sie diese Standardeinstellung für eine Migration in zwei Phasen. In der ersten Phase werden Warnungen bearbeitet. In der zweiten Phase schalten Sie die Anmerkungen zur Deklaration des erwarteten null-state einer Variablen ein. Wenn Sie diesen Standard verwenden, müssen Sie am Anfang jeder Datei ein #nullable disable hinzufügen.
  4. Nullable-Anmerkungen als Standard. Anmerkungen von Code vor dem Beheben von Warnungen.

Das Aktivieren von „nullable“ als Standard erzeugt zunächst mehr Aufwand, um die Präprozessordirektiven zu jeder Datei hinzuzufügen. Sie hat jedoch den Vorteil, dass jede neue Codedatei, die dem Projekt hinzugefügt wird, Nullable-fähig ist. Jede neue Arbeit ist Nullable-fähig. Nur bereits vorhandener Code muss aktualisiert werden. Die Deaktivierung von Nullable als Standard funktioniert besser, wenn die Bibliothek stabil ist und der Hauptschwerpunkt der Entwicklung auf der Einführung von Nullable-Verweistypen liegt. Aktivieren Sie Nullable-Verweistypen beim Kommentieren von APIs. Aktivieren Sie anschließend Nullable-Verweistypen für das gesamte Projekt. Wenn Sie eine neue Datei erstellen, müssen Sie die Präprozessordirektiven hinzufügen und nullable-fähig machen. Wenn Entwickler in Ihrem Team das vergessen, ist dieser neue Code nun im Arbeitsrückstand, da der gesamte Code Nullable-fähig gemacht werden muss.

Für welche Strategie Sie sich entscheiden, hängt davon ab, wie viel aktive Entwicklung in Ihrem Projekt stattfindet. Je ausgereifter und stabiler Ihr Projekt ist, umso besser eignet sich die zweite Strategie. Je mehr Features entwickelt werden, umso besser eignet sich die erste Strategie.

Wichtig

Der globale Nullable-Kontext gilt nicht für generierte Codedateien. Der Nullable-Kontext ist unabhängig von der Strategie für alle als generiert gekennzeichneten Quelldateien deaktiviert. Das bedeutet, dass alle in generierten Dateien enthaltenen APIs nicht mit Anmerkungen versehen werden. Es gibt viel Möglichkeiten, eine Datei als generiert zu markieren:

  1. Geben Sie in der EDITORCONFIG-Datei generated_code = true in einem Abschnitt an, der für diese Datei gilt.
  2. Fügen Sie <auto-generated> oder <auto-generated/> ganz oben in der Datei in einem Kommentar ein. Dabei kann es sich um eine beliebige Zeile des Kommentars handeln, jedoch muss es sich beim Kommentarblock um das erste Element in der Datei handeln.
  3. Beginnen Sie den Dateinamen mit TemporaryGeneratedFile_ .
  4. Enden Sie den Dateinamen mit .designer.cs, .generated.cs, .g.cs oder .g.i.cs.

Generatoren können die Präprozessoranweisung #nullable verwenden.

Verstehen von Zusammenhängen und Warnungen

Das Aktivieren von Warnungen und Anmerkungen steuert, wie der Compiler Verweistypen und Nullablility betrachtet. Jeder Typ hat eine von drei Nullabilities:

  • oblivious: Alle Verweistypen sind Nullable oblivious, wenn der Anmerkungskontext deaktiviert ist.
  • nonnullable: Ein nicht mit Anmerkungen versehener Verweistyp C ist nonnullable, wenn der Anmerkungskontext aktiviert ist.
  • Nullable: Ein mit Anmerkungen versehener Verweistyp C? ist nullable, es kann aber eine Warnung ausgegeben werden, wenn der Anmerkungskontext deaktiviert ist. Mit var deklarierte Variablen sind nullable, wenn der Anmerkungskontext aktiviert ist.

Der Compiler erzeugt anhand dieser Nullability Warnungen:

  • nonnullable-Typen erzeugen Warnungen, wenn ihnen ein potentieller null-Wert zugewiesen wird.
  • Nullable-Typen erzeugen Warnungen, wenn sie den Status maybe-null haben und dereferenziert werden.
  • oblivious-Typen verursachen Warnungen, wenn sie mit dem Status maybe-null dereferenziert werden und der Warnkontext aktiviert ist.

Jede Variable hat den Standardzustand „Nullable“, der von ihrer NULL-Zulässigkeit abhängt:

  • Nullable-Variablen haben einen Standard-Status null-state für maybe-null.
  • Nicht-Nullable-Variablen haben einen Standard-Status null-state für not-null.
  • Nullable oblivious-Variablen haben einen Standardstatus null-state von not-null.

Bevor Sie Nullable-Verweistypen aktivieren, sind alle Deklarationen in Ihrer Codebasis nullable oblivious. Das ist wichtig, weil damit alle Verweistypen einen Standardstatus null-state für not-null haben.

Bearbeiten von Warnungen

Wenn Ihr Projekt Entity Framework Core verwendet, sollten Sie die Anleitung zum Thema Arbeiten mit Nullable-Verweistypen lesen.

Wenn Sie mit der Migration beginnen, sollten Sie zunächst nur Warnungen aktivieren. Alle Deklarationen bleiben nullable oblivious, aber Sie werden Warnungen sehen, wenn Sie einen Wert dereferenzieren, nachdem sich sein null-state auf maybe-null ändert. Wenn Sie diese Warnungen bearbeiten, werden Sie an weiteren Stellen gegen NULL prüfen, und Ihre Codebasis wird fehlersicherer. Spezifische Techniken für verschiedene Situationen finden Sie in dem Artikel Techniken zur Auflösung von Nullable-Warnungen.

Sie können Warnungen bearbeiten und Anmerkungen in jeder Datei oder Klasse aktivieren, bevor Sie mit anderem Code fortfahren. Es ist jedoch oft effizienter, die Warnungen zu bearbeiten, die im Kontext Warnungen generiert werden, bevor die Typanmerkungen aktiviert sind. Auf diese Weise sind alle Typen oblivious, bis Sie die erste Gruppe von Warnungen bearbeitet haben.

Aktivieren von Typanmerkungen

Nachdem Sie den ersten Satz Warnungen bearbeitet haben, können Sie den Anmerkungskontext aktivieren. Dadurch ändern sich die Verweistypen von oblivious auf nonnullable. Alle mit var deklarierten Variablen sind nullable. Diese Änderung führt oft zu neuen Warnungen. Der erste Schritt zum Bearbeiten der Compiler-Warnungen ist die Verwendung von ?-Anmerkungen für Parameter- und Rückgabetypen, um anzuzeigen, wann Argumente oder Rückgabewerte null sein können. Bei dieser Aufgabe geht es nicht nur darum, Warnungen zu behandeln. Vielmehr geht es darum, dafür zu sorgen, dass der Compiler versteht, warum NULL-Werte verwendet werden sollen.

Attribute erweitern Typanmerkungen

Es wurden mehrere Attribute hinzugefügt, um zusätzliche Informationen über den NULL-Zustand von Variablen auszudrücken. Die Regeln für Ihre APIs sind für alle Parameter und Rückgabewerte wahrscheinlich komplizierter als not-null oder maybe-null. Viele Ihrer APIs umfassen komplexere Regeln in Bezug darauf, wann Variablen den Wert null annehmen können oder nicht. In diesen Fällen verwenden Sie Attribute, um diese Regeln auszudrücken. Die Attribute, die die Semantik Ihrer API beschreiben, finden Sie im Artikel Attributes that affect nullable analysis (Attribute, die die Nullable-Analyse betreffen).

Nächste Schritte

Sobald Sie alle Warnungen nach der Aktivierung von Anmerkungen behoben haben, können Sie den Standardkontext für Ihr Projekt auf aktiviert setzen. Wenn Sie in Ihrem Code Pragmas für die Nullable-Anmerkung oder den Warnkontext hinzugefügt haben, können Sie diese entfernen. Im Laufe der Zeit werden Sie möglicherweise neue Warnungen erhalten. Sie können Code schreiben, der Warnungen auslöst. Eine Bibliotheksabhängigkeit für Nullable-Verweistypen kann aktualisiert werden. Durch diese Aktualisierungen werden die Typen in dieser Bibliothek von nullable oblivious auf nonnullable oder nullable geändert.

Sie können diese Konzepte auch in unserem Lernmodul zur Nullsicherheit in C# erkunden.