Freigeben über


Nullwerte zulassende Verweistypen

Nullwert-Verweistypen sind Funktionen, die die Wahrscheinlichkeit minimieren, dass der Code die Auslösung einer System.NullReferenceException durch die Laufzeit verursacht. Drei Features, mit denen Sie diese Ausnahmen vermeiden können, einschließlich der Möglichkeit, einen Verweistyp explizit als nullablezu markieren:

  • Verbesserte statische Flowanalyse, die bestimmt, ob eine Variable null sein kann, bevor sie dereferenziert wird.
  • Attribute, die APIs mit Anmerkungen kommentieren, sodass die Flussanalyse den NULL-Status bestimmt.
  • Variablenanmerkungen, die Entwickler verwenden, um den beabsichtigten NULL-Zustand für eine Variable explizit zu deklarieren.

Der Compiler verfolgt den NULL-Zustand jedes Ausdrucks im Code zur Kompilierungszeit. Der NULL-Zustand hat einen von zwei Werten:

  • not-null: Der Ausdruck ist bekannt und nicht null.
  • maybe-null: Der Ausdruck könnte null sein.

Variablenanmerkungen bestimmen die NULL-Zulässigkeit einer Verweistypvariable:

  • non-nullable: Wenn Sie der Variablen einen null-Wert oder einen mybe-null-Ausdruck zuweisen, gibt der Compiler eine Warnung aus. Variablen, die non-nullable sind, haben einen Standard-NULL-Zustand not-null.
  • nullable: Sie können der Variablen einen null-Wert oder einen mybe-null-Ausdruck zuweisen. Wenn der NULL-Zustand der Variablen maybe-nullist, gibt der Compiler eine Warnung aus, wenn Sie die Variable dereferenzieren. Der Standard-NULL-Zustand für die Variable ist maybe-null.

Im restlichen Teil dieses Artikels wird beschrieben, wie diese drei Funktionsbereiche Warnungen generieren, wenn Ihr Code zur Dereferenzierung eines null -Werts führen könnte. Das Dereferenzieren einer Variablen bedeutet, mithilfe des .-Operators (Punkt) auf einen ihrer Member zuzugreifen, wie im folgenden Beispiel gezeigt:

string message = "Hello, World!";
int length = message.Length; // dereferencing "message"

Wenn Sie eine Variable dereferenzieren, deren Wert null ist, löst die Laufzeit eine System.NullReferenceException aus.

Ebenso können Warnungen erzeugt werden, wenn [] die Notation verwendet wird, um auf ein Element eines Objekts zuzugreifen, wenn das Objekt lautet null:

using System;

public class Collection<T>
{
    private T[] array = new T[100];
    public T this[int index]
    {
        get => array[index];
        set => array[index] = value;
    }
}

public static void Main()
{
    Collection<int> c = default;
    c[10] = 1;    // CS8602: Possible dereference of null
}

Behandelte Themen:

  • Die NULL-Zustand-Analyse des Compilers: wie der Compiler bestimmt, ob ein Ausdruck not-null oder maybe-null ist.
  • Attribute, die auf APIs angewendet werden, die mehr Kontext für die NULL-Zustand-Analyse des Compilers bereitstellen.
  • Nullwerte zulassende Variablenanmerkungen, die Informationen zu Ihrer Absicht für Variablen bereitstellen. Anmerkungen sind nützlich für Felder, Parameter und Rückgabewerte, um den Standard-NULL-Zustand festzulegen.
  • Die Regeln für generische Typargumente. Neue Einschränkungen wurden hinzugefügt, da Typparameter Verweistypen oder Werttypen sein können. Das Suffix ? wird für Nullwert zulassende Werttypen und Nullwert zulassende Verweistypen unterschiedlich implementiert.
  • Der Nullwert-Kontext hilft Ihnen beim Migrieren großer Projekte. Sie können Warnungen und Anmerkungen im Nullwert-Kontext in Teilen Ihrer App während der Migration aktivieren. Nachdem Sie weitere Warnungen angesprochen haben, können Sie beide Einstellungen für das gesamte Projekt aktivieren.

Schließlich erfahren Sie mehr über bekannte Fallstricke für die NULL-Zustand-Analyse in struct-Typen und -Arrays.

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

Nullzustandanalyse

Nullzustandanalyse verfolgt den null-state von Referenzen nach. Ein Ausdruck ist entweder not null oder maybe null. Der Compiler bestimmt auf zwei Arten, dass eine Variable nicht not-null ist:

  1. Die Variable wurde einem Wert zugewiesen, der bekanntermaßen nicht null ist.
  2. Die Variable wurde auf null überprüft und wurde seit dieser Überprüfung nicht zugewiesen.

Jede Variable, die der Compiler nicht als nicht-null identifizieren kann, wird als vielleicht-nullbetrachtet. Die Analyse liefert Warnungen in Situationen, in denen Sie einen null-Wert versehentlich dereferenzieren könnten. Der Compiler generiert Warnungen basierend auf dem NULL-Status.

  • Wenn eine Variable nicht Null ist, kann diese Variable sicher dereferenziert werden.
  • Wenn eine Variable maybe-null ist, muss diese Variable überprüft werden, um sicherzustellen, dass sie vor der Deferenzierung nicht null ist.

Betrachten Sie das folgenden Beispiel:

string? message = null;

// warning: dereference null.
Console.WriteLine($"The length of the message is {message.Length}");

var originalMessage = message;
message = "Hello, World!";

// No warning. Analysis determined "message" is not-null.
Console.WriteLine($"The length of the message is {message.Length}");

// warning!
Console.WriteLine(originalMessage.Length);

Im vorherigen Beispiel bestimmt der Compiler, dass messagemaybe-null ist, wenn die erste Meldung ausgegeben wird. Für die zweite Meldung wird keine Warnung angezeigt. Die letzte Codezeile generiert eine Warnung, weil originalMessage möglicherweise NULL ist. Das folgende Beispiel zeigt eine praktischere Verwendung, um eine Struktur von Knoten bis zum Stamm zu durchlaufen und jeden Knoten während des Durchlaufs zu verarbeiten:

void FindRoot(Node node, Action<Node> processNode)
{
    for (var current = node; current != null; current = current.Parent)
    {
        processNode(current);
    }
}

Der Code oben generiert keine Warnungen zum Dereferenzieren der Variablen current. Die statische Analyse bestimmt, dass current nie dereferenziert wird, wenn der Wert maybe-null ist. Die Variable current wird anhand von null überprüft, bevor auf current.Parent zugegriffen und current an die Aktion ProcessNode übergeben wird. Die vorherigen Beispiele zeigen, wie der Compiler den NULL-Status für lokale Variablen bestimmt, wenn initialisiert, zugewiesen oder mit null verglichen wird.

Die NULL-Zustand-Analyse führt keine Ablaufverfolgung in aufgerufene Methoden durch. Daher können Felder, die in einer allgemeinen Hilfsmethode initialisiert wurden, die von allen Konstruktoren aufgerufen wird, eine Warnung mit der folgenden Meldung generieren:

Die Non-Nullable-Eigenschaft Name muss beim Beenden des Konstruktors einen Wert ungleich NULL enthalten.

Es gibt zwei Möglichkeiten zur Lösung dieser Warnungen: Konstruktorverkettung oder Nullable-Attribute für die Hilfsmethode. Im folgenden Code ist ein Beispiel für jede Methode dargestellt. Die Person-Klasse verwendet einen gemeinsamen Konstruktor, der von allen anderen Konstruktoren aufgerufen wird. Die Student-Klasse verfügt über eine Hilfsmethode, die mit dem System.Diagnostics.CodeAnalysis.MemberNotNullAttribute-Attribut als Anmerkung versehen ist:


using System.Diagnostics.CodeAnalysis;

public class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }

    public Person(string firstName, string lastName)
    {
        FirstName = firstName;
        LastName = lastName;
    }

    public Person() : this("John", "Doe") { }
}

public class Student : Person
{
    public string Major { get; set; }

    public Student(string firstName, string lastName, string major)
        : base(firstName, lastName)
    {
        SetMajor(major);
    }

    public Student(string firstName, string lastName) :
        base(firstName, lastName)
    {
        SetMajor();
    }

    public Student()
    {
        SetMajor();
    }

    [MemberNotNull(nameof(Major))]
    private void SetMajor(string? major = default)
    {
        Major = major ?? "Undeclared";
    }
}

Die Nullable-Zustandsanalyse und die vom Compiler generierten Warnungen helfen Ihnen, Programmfehler durch Dereferenzierung von null zu vermeiden. Im Artikel Auflösen von Warnungen in Bezug auf Nullwerte zulassende Ausdrücke werden Techniken zum Beheben der Warnungen vorgestellt, die wahrscheinlich in Ihrem Code angezeigt werden. Die Diagnosen, die aus der Nullzustandsanalyse erzeugt werden, sind nur Warnungen.

Attribute für API-Signaturen

Die NULL-Zustand-Analyse benötigt Hinweise von Entwickler*innen, um die Semantik von APIs zu verstehen. Einige APIs bieten NULL-Überprüfungen und sollten den null-state einer Variablen von maybe-null in not-null ändern. Andere APIs geben Ausdrücke zurück, die not-null oder maybe-null sind, je nach dem null-state der Eingabeargumente. Sehen Sie sich beispielsweise den folgenden Code an, der eine Meldung in Großbuchstaben anzeigt:

void PrintMessageUpper(string? message)
{
    if (!IsNull(message))
    {
        Console.WriteLine($"{DateTime.Now}: {message.ToUpper()}");
    }
}

bool IsNull(string? s) => s == null;

Basierend auf der Überprüfung würde jeder Entwickler diesen Code als sicher betrachten, und er sollte keine Warnungen generieren. Der Compiler weiß jedoch nicht, dass IsNull eine NULL-Überprüfung bereitstellt und gibt eine Warnung für die message.ToUpper()-Anweisung aus, da er message für eine Variable vom Typ maybe-null hält. Verwenden Sie das NotNullWhen-Attribut, um diese Warnung zu beheben:

bool IsNull([NotNullWhen(false)] string? s) => s == null;

Dieses Attribut informiert den Compiler, dass, wenn IsNullfalse zurückgibt, der Parameter s nicht NULL ist. Der Compiler ändert den NULL-Zustand von message zu not-null im if (!IsNull(message)) {...}-Block. Es werden keine Warnungen ausgegeben.

Attribute bieten ausführliche Informationen zum NULL-Zustand von Argumenten, Rückgabewerten und Membern der Objektinstanz, die zum Aufrufen eines Members verwendet werden. Die Details zu den einzelnen Attributen finden Sie im Sprachreferenzartikel zu Nullable-Verweisattributen. Ab .NET 5 werden alle .NET-Laufzeit-APIs kommentiert. Sie verbessern die statische Analyse, indem Sie Ihre APIs kommentieren, um semantische Informationen zum null-state von Argumenten und Rückgabewerten zu liefern.

Nullable-Variablenanmerkungen

Die NULL-Zustand-Analyse bietet stabile Analysen für lokale Variablen. Der Compiler benötigt weitere Informationen von Ihnen für Membervariablen. Der Compiler benötigt weitere Informationen, um den NULL-Zustand aller Felder in der Eröffnungsklammer eines Members festzulegen. Jeder der zugreifbaren Konstruktoren kann verwendet werden, um das Objekt zu initialisieren. Wenn ein Memberfeld jemals auf null festgelegt werden kann, muss der Compiler davon ausgehen, dass sein null-status zu Beginn jeder Methode maybe-null ist.

Sie verwenden Anmerkungen, die deklarieren können, ob eine Variable ein Nullable-Verweistyp oder ein Nicht-Nullable-Verweistyp ist. Diese Anmerkungen enthalten wichtige Anweisungen zum null-state für Variablen:

  • Ein Verweis darf nicht NULL sein. Der Standardstatus einer keine Nullwerte zulassenden Verweisvariable ist not-null. Der Compiler erzwingt Regeln, die sicherstellen, dass das Dereferenzieren dieser Variablen sicher ist, ohne zuerst zu überprüfen, ob sie nicht NULL sind:
    • Die Variable muss mit einem Wert ungleich NULL initialisiert werden.
    • Der Variablen kann nie der Wert null zugewiesen werden. Der Compiler gibt eine Warnung aus, wenn der Code einen maybe-null-Ausdruck einer Variablen zuweist, die nicht NULL sein sollte.
  • Ein Verweis könnte NULL sein. Der Standardstatus einer Nullwerte zulassenden Verweisvariable ist maybe-null. Der Compiler erzwingt Regeln, um sicherzustellen, dass Sie ordnungsgemäß auf einen null-Verweis überprüfen:
    • Die Variable kann nur dereferenziert werden, wenn der Compiler garantieren kann, dass der Wert nicht nullist.
    • Diese Variablen können mit dem standardmäßigen null Wert initialisiert und in anderem Code dem Wert null zugewiesen werden.
    • Der Compiler gibt keine Warnungen aus, wenn Code einer Variablen, die NULL sein könnte, einen maybe-null-Ausdruck zuweist.

Eine Nicht-Nullwert-Referenzvariable hat den ursprünglichen null-state not-null. Jede Nullwerte zulassende Verweisvariable hat den ursprünglichen NULL-Zustandmaybe-null.

Ein Nullable-Verweistyp wird mithilfe der gleichen Syntax wie Nullable-Werttypen aufgeführt: Ein ? wird an den Variablentyp angefügt. Beispielsweise stellt die folgende Variablendeklaration eine Nullable-Zeichenfolgenvariable, name, dar:

string? name;

Wenn Nullwerte zulassende Verweistypen aktiviert sind, ist jede Variable, bei der ? nicht an den Typnamen angefügt ist, ein keine Nullwerte zulassender Verweistyp. Dies umfasst alle Verweistypvariablen in vorhandenem Code, sobald Sie dieses Feature aktiviert haben. Alle implizit typisierten lokalen Variablen (die mit var deklariert wurden) sind Nullable-Verweistypen. Wie in den vorherigen Abschnitten gezeigt, bestimmt die statische Analyse den NULL-Zustand lokaler Variablen, um zu ermitteln, ob sie maybe-null sind bevor sie dereferenziert wird.

Manchmal müssen Sie eine Warnung überschreiben, wenn Sie wissen, dass eine Variable nicht NULL ist, der Compiler aber bestimmt, dass der null-statemaybe-null ist. Sie verwenden den NULL-toleranten Operator! nach einem Variablennamen, um zu erzwingen, dass der null-statenot-null ist. Wenn Sie beispielsweise wissen, dass die Variable name nicht null ist, der Compiler aber eine Warnung ausgibt, können Sie folgenden Code schreiben, um die Analyse des Compilers zu überschreiben:

name!.Length;

Nullwerte zulassende-Verweistypen und Nullwerte zulassende Werttypen bieten ein ähnliches semantisches Konzept: Eine Variable kann einen Wert oder ein Objekt darstellen, oder diese Variable könnte null sein. Nullable-Verweistypen und Nullable-Werttypen werden jedoch unterschiedlich implementiert: Nullable-Werttypen werden mit System.Nullable<T> implementiert, und Nullable-Verweistypen werden durch Attribute implementiert, die vom Compiler gelesen werden. string? und string werden z. B. beide durch den gleichen Typ dargestellt: System.String. int? und int werden jedoch durch System.Nullable<System.Int32> bzw. System.Int32 dargestellt.

Nullable-Verweistypen sind ein Kompilierzeitfeature. Dies bedeutet, dass Aufrufer Warnungen ignorieren und bewusst null als Argument für eine Methode verwenden können, die einen Non-Nullable-Verweis erwartet. Autoren von Bibliotheken sollten Laufzeitüberprüfungen auf NULL-Argumentwerte integrieren. ArgumentNullException.ThrowIfNull ist die bevorzugte Option zur Laufzeitüberprüfung eines Parameters auf NULL. Darüber hinaus bleibt das Laufzeitverhalten eines Programms, das Nullwertannotationen verwendet, unverändert, wenn alle Nullwertannotationen (? und !) entfernt werden. Ihr einziger Zweck besteht darin, Entwurfsabsichten auszudrücken und Informationen für die Nullzustandsanalyse bereitzustellen.

Wichtig

Das Aktivieren von Nullable-Anmerkungen kann die Art und Weise ändern, mit der Entity Framework Core bestimmt, ob ein Datenmember erforderlich ist. Weitere Einzelheiten finden Sie im Artikel Entity Framework Core-Grundlagen: Arbeiten mit Nullable-Verweistypen.

Generics

Generics erfordern detaillierte Regeln zur Behandlung von T? für jeden Typparameter T. Die Regeln sind aufgrund des bisherigen Verlaufs und der unterschiedlichen Implementierung für einen Nullwerte zulassende Werttyp und einen Nullwerte zulassende Verweistyp notwendigerweise ausführlich. Nullwerte zulassende Werttypen werden mit der Struktur System.Nullable<T> implementiert. Nullwerte zulassende Verweistypen werden als Typ-Anmerkungen implementiert, die dem Compiler semantische Regeln vorgeben.

  • Wenn das Typargument für T ein Verweistyp ist, verweist T? auf den entsprechenden Nullwerte zulassenden Verweistyp. Wenn zum Beispiel T ein string ist, dann ist T? ein string?.
  • Wenn das Typargument für T ein Wertetyp ist, verweist T? auf denselben Wertetyp, T. Wenn zum Beispiel T ein int ist, ist auch T? ein int.
  • Wenn das Typargument für T ein löschbarer Verweistyp ist, verweist T? auf denselben löschbaren Verweistyp. Wenn zum Beispiel T ein string? ist, dann ist T? auch ein string?.
  • Wenn das Typargument für T ein löschbarer Werttyp ist, verweist T? auf denselben löschbaren Werttyp. Wenn zum Beispiel T ein int? ist, dann ist T? auch ein int?.

Bei Rückgabewerten ist T? äquivalent zu [MaybeNull]T; für Argumentwerte ist T? äquivalent zu [AllowNull]T. Weitere Informationen finden Sie im Artikel Attribute für die Nullzustandsanalyse in der Sprachreferenz.

Mit Einschränkungen können Sie ein anderes Verhalten festlegen:

  • Die class-Einschränkung bedeutet, dass T ein keine Nullwerte zulassender Verweistyp sein muss (z. B. string). Der Compiler gibt eine Warnung aus, wenn Sie einen Nullwerte zulassenden Verweistyp verwenden, z. B. string? für T.
  • Die class?-Einschränkung bedeutet, dass T ein Verweistyp sein muss, entweder ein keine Nullwerte zulassender (string) oder ein Nullwerte zulassender Verweistyp (z. B. string?). Wenn der Typparameter ein löschbarer Verweistyp ist, z. B. string?, verweist ein Ausdruck von T? auf denselben löschbaren Verweistyp, z. B. string?.
  • Die notnull-Einschränkung bedeutet, dass T ein Non-Nullable-Verweistyp oder ein Non-Nullable-Werttyp sein muss. Wenn Sie einen Nullwerte zulassende Verweistyp oder einen Nullwerte zulassende Werttyp für den Typparameter verwenden, generiert der Compiler eine Warnung. Wenn T ein Werttyp ist, ist der Rückgabewert dieser Werttyp und nicht der entsprechende löschbare Werttyp.

Diese Einschränkungen helfen dem Compiler, weitere Informationen zur Verwendung von T zu erhalten. Dies hilft, wenn Entwickler*innen den Typ für T auswählen, und bietet eine bessere NULL-Zustand-Analyse, wenn eine Instanz des generischen Typs verwendet wird.

Nullable-Kontext

Der Nullwert-Kontext legt fest, wie Nullwert-Referenztypannotationen verarbeitet werden und welche Warnungen durch die statische Nullzustandsanalyse generiert werden. Der Nullwert-Kontext enthält zwei Flags: die Einstellung für Anmerkungen und die Einstellung für Warnungen.

Sowohl die Anmerkungs--Einstellungen als auch die Warnungs--Einstellungen sind für vorhandene Projekte standardmäßig deaktiviert. Ab .NET 6 (C# 10) sind beide Flags standardmäßig für neue Projekte aktiviert. Der Grund für zwei unterschiedlichen Flags für den Nullwert-Kontext ist die Vereinfachung der Migration großer Projekte, die vor der Einführung von Nullwert-Referenztypen entwickelt wurden.

Bei kleinen Projekten können Sie Nullwerte zulassende Verweistypen aktivieren, Warnungen beheben und fortfahren. Bei größeren Projekten und Projektlösungen mit mehreren Projekten kann dies jedoch zu einer großen Anzahl von Warnungen führen. Sie können Pragmen verwenden, um Nullwerte zulassende Verweistypen Datei-für-Datei zu aktivieren, während Sie sich mit der Verwendung von Nullwerte zulassenden Verweistypen beschäftigen. Die neuen Features, die vor dem Auslösen von System.NullReferenceException schützen, können störend sein, wenn sie in einer vorhandenen Codebasis aktiviert werden:

  • Alle explizit typisierten Verweisvariablen werden als Non-Nullable-Verweistypen interpretiert.
  • Die Bedeutung der class-Einschränkung in Generika wurde geändert, um einen Non-Nullable-Verweistyp anzugeben.
  • Aufgrund dieser neuen Regeln werden neue Warnungen generiert.

Der Nullable-Anmerkungskontext bestimmt das Verhalten des Compilers. Es gibt vier Kombinationen für die Einstellungen für den Nullwert-Kontext:

  • both disabled: Der Code ist nullable-oblivious. Disable stimmt mit dem Verhalten überein, bevor Nullwerte zulassende Verweistypen aktiviert wurden. Die neue Syntax erzeugt allerdings Warnungen anstelle von Fehlern.
    • Nullable-Warnungen sind deaktiviert.
    • Alle Verweistypvariablen sind Nullable-Verweistypen.
    • Verwenden Sie das Suffix ? verwenden, um einen Nullable-Verweistyp zu deklarieren, der eine Warnung generiert.
    • Sie können den NULL-toleranten Operator (!) verwenden, das hat aber keine Auswirkungen.
  • both enabled: Der Compiler unterstützt alle Nullreferenzanalysen und alle Sprachfunktionen.
    • Alle neuen Nullable-Warnungen sind aktiviert.
    • Sie können das Suffix ? verwenden, um einen Nullable-Verweistyp zu deklarieren.
    • Verweistypvariablen ohne das Suffix ? sind keine Nullwerte zulassenden Verweistypen.
    • Der Null-Verzeihungsoperator unterdrückt Warnungen für eine mögliche Ableitung von null.
  • warning enabled: Der Compiler führt alle Nullanalysen aus und gibt Warnungen aus, wenn Code null dereferenzieren könnte.
    • Alle neuen Nullable-Warnungen sind aktiviert.
    • Verwenden Sie das Suffix ? verwenden, um einen Nullable-Verweistyp zu deklarieren, der eine Warnung generiert.
    • Alle Verweistypvariablen dürfen NULL sein. Member haben jedoch den null-statenot-null an der öffnenden geschweiften Klammer aller Methoden, es sei denn, sie werden mit dem Suffix ? deklariert.
    • Sie können den NULL-toleranten Operator (!) verwenden.
  • annotations enabled: Der Compiler gibt keine Warnungen aus, wenn Code null dereferenzieren könnte oder wenn Sie einem möglichen Nullwert-Ausdruck eine Nicht-Nullwert-Variable zuweisen.
    • Alle neuen Nullable-Warnungen sind deaktiviert.
    • Sie können das Suffix ? verwenden, um einen Nullable-Verweistyp zu deklarieren.
    • Verweistypvariablen ohne das Suffix ? sind keine Nullwerte zulassenden Verweistypen.
    • Sie können den NULL-toleranten Operator (!) verwenden, das hat aber keine Auswirkungen.

Der Nullable-Anmerkungskontext und der Nullable-Warnungskontext können für ein Projekt festgelegt werden, indem Sie das <Nullable>-Element in Ihrer .csproj-Datei verwenden. Dieses Element konfiguriert, wie der Compiler die NULL-Zulässigkeit von Typen interpretiert und welche Warnungen ausgegeben werden. In der folgenden Tabelle sind die zulässigen Werte aufgeführt und die von ihnen angegebenen Kontexte zusammengefasst.

Kontext Dereferenzierungswarnungen Zuweisungswarnungen Verweistypen ?-Suffix !-Operator
disable Disabled Disabled Alle lassen Nullwerte zu. Erzeugt eine Warnung Hat keine Auswirkungen.
enable Aktiviert Aktiviert Non-nullable, es sei denn, es wurde mit ? deklariert Deklariert einen Nullable-Typ Unterdrückt Warnungen für mögliche null-Zuweisungen.
warnings Aktiviert Nicht zutreffend Alle lassen Nullwerte zu, aber die Member werden bei der Eröffnungsklammer von Methoden als not-null betrachtet Erzeugt eine Warnung Unterdrückt Warnungen für mögliche null-Zuweisungen.
annotations Disabled Disabled Non-nullable, es sei denn, es wurde mit ? deklariert Deklariert einen Nullable-Typ Hat keine Auswirkungen.

Für Verweistypvariablen in Code, der in einem disable-Kontext kompiliert wurde, erfolgt keine Nullable-Beachtung. Sie können ein null-Literal oder eine maybe-null-Variable einer Variablen zuweisen, die nullable-oblivious ist. Der Standardzustand einer Variable mit der Eigenschaft Nullwerte zulassend-nicht beachtend ist jedoch nicht-null.

Sie können auswählen, welche Einstellung für Ihr Projekt am besten geeignet ist:

  • Wählen Sie disable für Legacyprojekte, die Sie nicht aufgrund von Diagnosen oder neuen Features aktualisieren möchten.
  • Wählen Sie Warnungen aus, um zu bestimmen, wo Ihr Code möglicherweise System.NullReferenceExceptions auslösen kann. Sie können diese Warnungen beheben, bevor Sie den Code ändern, um Non-Nullable-Verweistypen zu aktivieren.
  • Wählen Sie annotations aus, um Ihre Entwurfsabsicht auszudrücken, bevor Sie Warnungen aktivieren.
  • Wählen Sie enable für neue Projekte und aktive Projekte, die Sie vor NULL-Verweisausnahmen schützen möchten.

Beispiel:

<Nullable>enable</Nullable>

Sie können auch Direktiven verwenden, um dieselben Flags an einer beliebigen Stelle im Quellcode festzulegen. Diese Anweisungen sind besonders nützlich, wenn Sie eine große Codebasis migrieren.

  • #nullable enable: Legt die Anmerkungs- und Warnungsflags auf aktivieren fest.
  • #nullable disable: Legt die Anmerkungs- und Warnungsflags auf deaktivieren fest.
  • #nullable restore: Führt eine Wiederherstellung der Anmerkungs- und Warnungsflags zu den Projekteinstellungen aus.
  • #nullable disable warnings: Legt das Warnungsflag auf deaktivieren fest.
  • #nullable enable warnings: Legt das Warnungsflag auf aktivieren fest.
  • #nullable restore warnings: Führt eine Wiederherstellung des Warnungsflags auf die Projekteinstellungen aus.
  • #nullable disable annotations: Legt das Anmerkungsflag auf deaktivieren fest.
  • #nullable enable annotations: Legt das Anmerkungsflag auf aktivieren fest.
  • #nullable restore annotations: Führt eine Wiederherstellung des Anmerkungsflags auf die Projekteinstellungen aus.

Für jede Codezeile können Sie eine der folgenden Kombinationen festlegen:

Warnflagge Anmerkungsflag Zweck
Standardeinstellung des Projekts Standardeinstellung des Projekts Standard
enable disable Analysewarnungen korrigieren
enable Standardeinstellung des Projekts Analysewarnungen korrigieren
Standardeinstellung des Projekts enable Typanmerkungen hinzufügen
enable enable Bereits migrierter Code
disable enable Kommentieren von Code vor dem Beheben von Warnungen
disable disable Hinzufügen von Legacycode zum migrierten Projekt
Standardeinstellung des Projekts disable Selten
disable Standardeinstellung des Projekts Selten

Mit diesen neun Kombinationen können Sie die Diagnosen, die der Compiler für Ihren Code ausgibt, detailliert steuern. Sie können weitere Features in jedem Bereich aktivieren, den Sie aktualisieren, ohne weitere Warnungen zu erhalten, die Sie noch nicht beheben möchten.

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. Für generierte Dateien werden keine Nullwertwarnungen erstellt. 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.

Standardmäßig sind Nullwert-Anmerkungs- und -Warnungsflags deaktiviert. Dies bedeutet, dass Ihr vorhandener Code ohne Änderungen und ohne Warnungen kompiliert wird. Ab .NET 6 enthalten neue Projekte in allen Projektvorlagen das Element <Nullable>enable</Nullable>. Daher sind diese Flags auf aktiviert festgelegt.

Diese Optionen bieten zwei unterschiedliche Strategien zum Aktualisieren einer vorhandenen Codebasis, um Nullable-Verweistypen zu verwenden.

Bekannte Fehlerquellen

Arrays und Strukturen, die Verweistypen enthalten, sind bekannte Fallstricke in Nullable-Verweisen und in der statischen Analyse, die die NULL-Sicherheit bestimmt. In beiden Fällen kann ein keine Nullwerte zulassender-Verweis mit null initialisiert werden, ohne Warnungen zu generieren.

Strukturen

Strukturen, die Verweistypen enthalten, die keine NULL-Werte zulassen, können Sie default zuweisen, ohne dass Warnungen ausgelöst werden. Betrachten Sie das folgenden Beispiel:

using System;

#nullable enable

public struct Student
{
    public string FirstName;
    public string? MiddleName;
    public string LastName;
}

public static class Program
{
    public static void PrintStudent(Student student)
    {
        Console.WriteLine($"First name: {student.FirstName.ToUpper()}");
        Console.WriteLine($"Middle name: {student.MiddleName?.ToUpper()}");
        Console.WriteLine($"Last name: {student.LastName.ToUpper()}");
    }

    public static void Main() => PrintStudent(default);
}

Im Beispiel oben gibt es in PrintStudent(default) keine Warnung, wenn die Non-Nullable-Verweistypen FirstName und LastName NULL sind.

Bei der Verwendung von generischen Strukturen tritt ein weiteres häufigeres Problem auf. Betrachten Sie das folgenden Beispiel:

#nullable enable

public struct S<T>
{
    public T Prop { get; set; }
}

public static class Program
{
    public static void Main()
    {
        string s = default(S<string>).Prop;
    }
}

Im vorherigen Beispiel ist die Eigenschaft Prop bei Laufzeit null. Sie wird non-nullable Zeichenfolgen ohne Warnungen zugewiesen.

Arrays

Arrays stellen ebenfalls eine bekannte Fehlerquelle in Verweistypen dar, die NULL-Werte zulassen. Sehen Sie sich das folgende Beispiel an, das keine Warnungen auslöst:

using System;

#nullable enable

public static class Program
{
    public static void Main()
    {
        string[] values = new string[10];
        string s = values[0];
        Console.WriteLine(s.ToUpper());
    }
}

Im Beispiel oben zeigt die Deklaration des Arrays, dass dieses Non-Nullable-Zeichenfolgen enthält, während alle seine Elemente mit null initialisiert werden. Anschließend wird der Variablen s ein null-Wert (das erste Element des Arrays) zugewiesen. Schließlich wird die Variable s dereferenziert, was zu einer Laufzeitausnahme führt.

Siehe auch