Nullwerte zulassende Verweistypen

In einem nullablen unveränderlichen Kontext waren alle Verweistypen nullfähig. Nullfähige Referenztypen beziehen sich auf eine Gruppe von Features, die in einem nullfähigen Kontext aktiviert sind, mit dem die Wahrscheinlichkeit minimiert wird, dass der Code die Laufzeit auslöst System.NullReferenceException. Nullwerte zulassende Verweistypen enthalten drei Features, mit denen Sie diese Ausnahmen vermeiden können (einschließlich der Möglichkeit, einen Verweistyp explizit als Nullwerte zulassend zu kennzeichnen):

  • Verbesserte statische Flussanalyse, 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.

Nullzustandsanalyse und Variablenanmerkungen sind standardmäßig für vorhandene Projekte deaktiviert, was bedeutet, dass alle Verweistypen weiterhin nullfähig sind. Ab .NET 6 sind sie standardmäßig für neue Projekte aktiviert. Informationen zum Aktivieren dieser Features durch Deklarieren eines Nullable-Anmerkungskontexts finden Sie unter Nullable-Kontexte.

Im restlichen Teil dieses Artikels wird beschrieben, wie diese drei Featurebereiche funktionieren, um Warnungen zu generieren, wenn Ihr Code möglicherweise einen null-Wert dereferenziert. 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.

Sie können diese Konzepte auch in unserem Lernmodul zu Nullable Safety in C# erkunden.

Analyse des NULL-Status

Die Nullzustandsanalyse verfolgt den Nullstatus von Verweisen. Diese statische Analyse gibt Warnungen aus, wenn Ihr Code möglicherweise null dereferenziert. Sie können diese Warnungen behandeln, um die Fälle zu minimieren, in denen die Laufzeit eine System.NullReferenceException auslöst. Der Compiler verwendet statische Analyse, um den NULL-Status einer Variablen zu bestimmen. Eine Variable 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 bekannt ist, dass er nicht null ist.
  2. Die Variable wurde mit null überprüft und seit dieser Überprüfung nicht mehr geändert.

Jede Variable, die der Compiler nicht als not-null bestimmt hat, wird als maybe-null betrachtet. Die Analyse liefert Warnungen in Situationen, in denen Sie einen null-Wert versehentlich dereferenzieren können. Der Compiler generiert Warnungen basierend auf dem NULL-Status.

  • Wenn eine Variable not-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 Nullzustandsanalyse wird nicht in aufgerufene Methoden nachverfolgt. Daher werden felder, die in einer allgemeinen Hilfsmethode initialisiert werden, die von Konstruktoren aufgerufen wird, eine Warnung mit der folgenden Vorlage generieren:

Nicht nullfähige Eigenschaft 'name' muss beim Beenden des Konstruktors einen Wert ohne Null enthalten.

Sie können diese Warnungen auf eine von zwei Arten adressieren: Konstruktorkette oder nullfähige 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 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";
    }
}

Hinweis

In C# 10 wurde die eindeutige Zuweisung und die Analyse des NULL-Status verbessert. Wenn Sie ein Upgrade auf C# 10 durchführen, werden möglicherweise weniger Nullable-Warnungen angezeigt, die falsch positiv sind. Weitere Informationen zu den Verbesserungen finden Sie in der Featurespezifikation für Verbesserungen an der eindeutigen Zuweisung.

Die Analyse des nullfähigen Zustands und die Warnungen, die vom Compiler generiert werden, helfen Ihnen, Programmfehler zu vermeiden, indem Sie die Ableitung nullausführen. Der Artikel zum Auflösen von Nullablenwarnungen bietet Techniken zum Korrigieren der Warnungen, die Sie wahrscheinlich in Ihrem Code sehen.

Attribute für API-Signaturen

Die NULL-Statusanalyse benötigt Hinweise von Entwicklern, 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 anzeigt:

public void PrintMessage(string message)
{
    if (!string.IsNullOrWhiteSpace(message))
    {
        Console.WriteLine($"{DateTime.Now}: {message}");
    }
}

Basierend auf der Überprüfung würde jeder Entwickler diesen Code als sicher betrachten, und er sollte keine Warnungen generieren. Der Compiler weiß nicht, dass IsNullOrWhiteSpace eine NULL-Überprüfung bereitstellt. Sie wenden Attribute an, um den Compiler darüber zu informieren, dass messagenot-null ist, wenn IsNullOrWhiteSpacefalse zurückgibt (und nur dann). Im vorherigen Beispiel enthält die Signatur NotNullWhen, um den NULL-Status von message anzugeben:

public static bool IsNullOrWhiteSpace([NotNullWhen(false)] string message);

Attribute bieten ausführliche Informationen zum NULL-Status 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. Alle .NET-Runtime-APIs wurden in .NET 5 mit Anmerkungen 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-state-Analyse bietet stabile Analysen für die meisten Variablen. Der Compiler benötigt weitere Informationen von Ihnen für Membervariablen. Der Compiler kann keine Annahmen über die Reihenfolge treffen, in der auf öffentliche Member zugegriffen wird. Auf alle öffentlichen Member könnte in beliebiger Reihenfolge zugegriffen werden. 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 nicht-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 darf 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üft haben:
    • Die Variable kann nur dereferenziert werden, wenn der Compiler garantieren kann, dass der Wert nicht null ist.
    • Diese Variablen können mit dem Standardwert null initialisiert und in anderem Code dem Wert null zugewiesen werden.
    • Der Compiler gibt keine Warnungen aus, wenn Code einer Variablen, die NULL sein kann, einen maybe-null-Ausdruck zuweist.

Jede Verweisvariable, die nicht null sein soll, weist den null-statenot-null auf. Jede Verweisvariable, die anfänglich null sein kann, hat den null-statemaybe-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;

Bei jeder Variable, bei der ? nicht an den Typnamen angefügt ist, handelt es sich um einen Non-Nullable-Verweistyp. Dies umfasst alle Verweistypvariablen in vorhandenem Code, wenn 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-state lokaler Variablen, um zu ermitteln, ob sie maybe-null sind.

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-Verzeihoperator! nach einem Variablennamen, um zu erzwingen, dass der NULL-Zustand nicht 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;

Nullable-Verweistypen und Nullable-Werttypen bieten ein ähnliches semantisches Konzept: Eine Variable kann einen Wert oder ein Objekt darstellen, oder diese Variable kann 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.

Nullfähige Referenztypen sind ein Kompilierungszeitfeature. Dies bedeutet, dass Aufrufer Warnungen ignorieren können, absichtlich als Argument für eine Methode verwendet null werden, die einen nicht nullbaren Verweis erwartet. Bibliotheksautoren sollten Laufzeitüberprüfungen auf Nullargumentwerte enthalten. Dies ArgumentNullException.ThrowIfNull ist die bevorzugte Option zum Überprüfen eines Parameters auf null zur Laufzeit.

Wichtig

Durch Aktivieren von Nullablenanmerkungen kann sich ändern, wie Entity Framework Core bestimmt, ob ein Datenelement erforderlich ist. Weitere Informationen finden Sie im Artikel zu Entity Framework Core Fundamentals: Arbeiten mit Nullable Reference Types.

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 den Typ für T auswählen, und bietet eine bessere null-state-Analyse, wenn eine Instanz des generischen Typs verwendet wird.

Nullable-Kontexte

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.

Sie müssen sich ausdrücklich für die Nutzung dieser Funktionen in Ihren bestehenden Projekten entscheiden. Dies bietet einen Migrationspfad und bewahrt Abwärtskompatibilität. Nullable-Kontexte ermöglichen eine differenzierte Steuerung der Interpretation von Verweistypvariablen durch den Compiler. Der Nullable-Anmerkungskontext bestimmt das Verhalten des Compilers. Es gibt vier Werte für den Nullable-Anmerkungskontext:

  • disable: The code is nullable oblivious.
    • Nullable-Warnungen sind deaktiviert.
    • Alle Verweistypvariablen sind Nullable-Verweistypen.
    • Sie können eine Variable nicht als Nullable-Verweistyp deklarieren, indem Sie das Suffix ? für den Typ verwenden.
    • Sie können den NULL-toleranten Operator (!) verwenden, das hat aber keine Auswirkungen.
  • enable: The compiler enable all null reference analysis and all language features.
    • Alle neuen Nullable-Warnungen sind aktiviert.
    • Sie können das Suffix ? verwenden, um einen Nullable-Verweistyp zu deklarieren.
    • Alle anderen Verweistypvariablen sind Non-Nullable-Verweistypen.
    • Der NULL-tolerante Operator unterdrückt Warnungen für eine mögliche Zuweisung zu null.
  • warnings: Der Compiler führt alle NULL-Analysen durch und gibt Warnungen aus, wenn Code möglicherweise null dereferenziert.
    • 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: Der Compiler führt keine NULL-Analyse durch oder gibt Warnungen aus, wenn Code möglicherweise null dereferenziert.
    • Alle neuen Nullable-Warnungen sind deaktiviert.
    • Sie können das Suffix ? verwenden, um einen Nullable-Verweistyp zu deklarieren.
    • Alle anderen Verweistypvariablen sind Non-Nullable-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. Kann nicht verwendet werden. 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 verfügbar Alle lassen Nullwerte zu, aber Member werden bei öffnenden geschweiften Klammern von Methoden als nicht 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.

Referenztypvariablen im Code, der in einem deaktivierten Kontext kompiliert wird, sind nullable-oblivious. Sie können ein null-Literal oder eine maybe-null-Variable einer Variablen zuweisen, die Nullwerte zulassend-nicht beachtend 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 die Option "Deaktivieren" für Ältere Projekte aus, die Sie nicht basierend auf diagnosen oder neuen Features aktualisieren möchten.
  • Wählen Sie warnings 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 "Aktivieren " für neue Projekte und aktive Projekte aus, in denen Sie vor Nullreferenz ausnahmen schützen möchten.

Beispiel:

<Nullable>enable</Nullable>

Sie können auch Anweisungen verwenden, um diese gleichen Kontexte an beliebiger Stelle in Ihrem Quellcode festzulegen. Diese sind besonders nützlich, wenn Sie eine große Codebasis migrieren.

  • #nullable enable: Legt den Nullable-Anmerkungskontext und den nullablen Warnungskontext fest, der aktiviert werden soll.
  • #nullable disable: Legt den Nullable-Anmerkungskontext und den nullablen Warnungskontext fest, um zu deaktivieren.
  • #nullable restore: Stellt die Projekteinstellungen für den Nullable-Anmerkungskontext und den Nullable-Warnungskontext wieder her.
  • #nullable disable warnings: Legen Sie den Nullable-Warnungskontext fest, um zu deaktivieren.
  • #nullable enable warnings: Legen Sie den nullablen Warnungskontext fest, der aktiviert werden soll.
  • #nullable restore warnings: Stellt die Projekteinstellungen für den Nullable-Warnungskontext wieder her.
  • #nullable disable annotations: Legen Sie den Nullanmerkungskontext fest, der deaktiviert werden soll.
  • #nullable enable annotations: Legen Sie den nullablen Anmerkungskontext fest, der aktiviert werden soll.
  • #nullable restore annotations: Stellt die Projekteinstellungen für den Anmerkungswarnungskontext wieder her.

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

Warnungskontext Anmerkungskontext 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 zusätzliche 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. 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 die Nullable-Anmerkungs- und -Warnungskontexte deaktiviert. Dies bedeutet, dass Ihr vorhandener Code ohne Änderungen und ohne Warnungen kompiliert wird. Ab .NET 6 enthalten neue Projekte das <Nullable>enable</Nullable>-Element in allen Projektvorlagen.

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 Non-Nullable-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 Foo<T>
{
    public T Bar { get; set; }
}

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

Im obigen Beispiel entspricht die Eigenschaft Bar zur Laufzeit null, und sie wird einer Non-Nullable-Zeichenfolge zugewiesen, ohne dass eine Warnung ausgelöst wird.

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