Ereignisse
17. März, 23 Uhr - 21. März, 23 Uhr
Nehmen Sie an der Meetup-Serie teil, um skalierbare KI-Lösungen basierend auf realen Anwendungsfällen mit Mitentwicklern und Experten zu erstellen.
Jetzt registrierenDieser Browser wird nicht mehr unterstützt.
Führen Sie ein Upgrade auf Microsoft Edge durch, um die neuesten Features, Sicherheitsupdates und den technischen Support zu nutzen.
In diesem Artikel werden die folgenden Compilerwarnungen behandelt:
[NotNull]
oder [DisallowNull]
markierten Typ verwendet werden.[DoesNotReturn]
gekennzeichnete Methode darf nicht zurückgegeben werden.[DoesNotReturn]
für den Abgleich mit dem implementierten oder überschriebenen Member.Der Zweck von Nullwerte zulassenden Warnungen besteht darin, die Wahrscheinlichkeit zu minimieren, dass Ihre Anwendung bei der Ausführung eine System.NullReferenceException auslöst. Um dieses Ziel zu erreichen, verwendet der Compiler statische Analysen und gibt Warnungen aus, wenn Ihr Code über Konstrukte verfügt, die zu NULL-Verweisausnahmen führen können. Sie stellen dem Compiler Informationen für seine statische Analyse bereit, indem Sie Typanmerkungen und Attribute anwenden. Diese Anmerkungen und Attribute beschreiben die NULL-Zulässigkeit von Argumenten, Parametern und Membern Ihrer Typen. In diesem Artikel lernen Sie verschiedene Techniken für die Behandlung von Nullable-Warnungen kennen, die der Compiler aus seiner statischen Analyse generiert. Die hier beschriebenen Techniken gelten für allgemeinen C#-Code. Informationen zum Arbeiten mit Nullable-Verweistypen und Entity Framework Core finden Sie unter Arbeiten mit Nullable-Verweistypen.
Sie können fast alle Warnungen mit einer von vier Techniken behandeln:
?
oder !
.Diese Gruppe von Warnungen informiert Sie, dass Sie eine Variable, deren NULL-Zustandmaybe-null ist, dereferenzieren. Diese Warnungen sind:
Der folgende Code veranschaulicht ein Beispiel für jede der vorherigen Warnungen:
class Container
{
public List<string>? States { get; set; }
}
internal void PossibleDereferenceNullExamples(string? message)
{
Console.WriteLine(message.Length); // CS8602
var c = new Container { States = { "Red", "Yellow", "Green" } }; // CS8670
}
Im obigen Beispiel ist die Warnung darauf zurückzuführen, dass Container
, c
, für die Eigenschaft States
einen NULL-Wert aufweisen kann. Durch das Zuweisen neuer Zustände zu einer Auflistung, die möglicherweise NULL ist, wird die Warnung verursacht.
Um diese Warnungen zu entfernen, müssen Sie Code hinzufügen, um den NULL-Zustand dieser Variablen in not-null zu ändern, bevor Sie sie dereferenzieren. Die Warnung des Auflistungsinitialisierers kann schwieriger zu erkennen sein. Der Compiler erkennt, dass die Auflistung maybe-null ist, wenn der Initialisierer ihr Elemente hinzufügt.
In vielen Fällen können Sie diese Warnungen beheben, indem Sie überprüfen, ob eine Variable nicht NULL ist, bevor Sie sie dereferenzieren. Im Folgenden wird vor der Dereferenzierung des message
-Parameters eine NULL-Überprüfung hinzufügt:
void WriteMessageLength(string? message)
{
if (message is not null)
{
Console.WriteLine(message.Length);
}
}
Im folgenden Beispiel wird der Sicherungsspeicher für States
initialisiert und die set
-Zugriffsmethode entfernt. Consumer der Klasse können den Inhalt der Sammlung ändern, und der Speicher für die Sammlung ist nie null
:
class Container
{
public List<string> States { get; } = new();
}
Andere Vorkommen dieser Warnungen können falsch positiv sein. Möglicherweise verfügen Sie über eine private Hilfsmethode, die auf NULL prüft. Der Compiler weiß nicht, dass die Methode eine NULL-Überprüfung durchführt. Betrachten Sie das folgende Beispiel, das eine private Hilfsmethode, IsNotNull
, verwendet:
public void WriteMessage(string? message)
{
if (IsNotNull(message))
Console.WriteLine(message.Length);
}
Der Compiler gibt eine Warmung mit dem Hinweis aus, Sie beim Schreiben der Eigenschaft message.Length
u. U. NULL dereferenzieren, da die statische Analyse bestimmt, dass message
möglicherweise null
sein kann. Vielleicht wissen Sie, dass IsNotNull
eine NULL-Überprüfung ermöglicht, und wenn true
zurückgegeben wird, sollte der NULL-Zustand von message
not-null sein. Sie müssen dem Compiler diese Fakten mitteilen. Eine Möglichkeit besteht darin, den NULL-toleranten Operator (!
) zu verwenden. Sie können die WriteLine
-Anweisung so ändern, dass sie dem folgenden Code entspricht:
Console.WriteLine(message!.Length);
Der NULL-tolerante Operator macht den Ausdruck not-null, auch wenn er ohne Anwendung von !
maybe-null war. In diesem Beispiel besteht eine bessere Lösung darin, der Signatur von IsNotNull
ein Attribut hinzuzufügen:
private static bool IsNotNull([NotNullWhen(true)] object? obj) => obj != null;
Das System.Diagnostics.CodeAnalysis.NotNullWhenAttribute informiert den Compiler, dass das für den obj
-Parameter verwendete Argument not-null ist, wenn die Methode true
zurückgibt. Wenn die Methode false
zurückgibt, weist das Argument den gleichen NULL-Zustand wie vor dem Aufruf der Methode auf.
Tipp
Es gibt eine Vielzahl von Attributen, mit denen Sie beschreiben können, wie Sich Ihre Methoden und Eigenschaften auf den NULL-Zustand auswirken. Informationen dazu finden Sie im Artikel der Sprachreferenz zu Attributen für die statische Analyse des NULL-Zustands.
Zum Beheben einer Warnung zur Deferenzierung einer maybe-null-Variablen gibt es drei Techniken:
!
auf den Ausdruck an, um den Zustand auf not-null zu zwingen.Dieser Satz von Warnungen benachrichtigt Sie, dass Sie eine Variable mit Non-Nullable-Typ einem Ausdruck zuweisen, dessen NULL-Zustandmaybe-null ist. Diese Warnungen sind:
Der Compiler gibt diese Warnungen aus, wenn Sie versuchen, einer Non-Nullable-Variablen einen Ausdruck zuzuweisen, der maybe-null ist. Beispiel:
string? TryGetMessage(int id) => "";
string msg = TryGetMessage(42); // Possible null assignment.
Die verschiedenen Warnungen geben Details zum Code an, z. B. Zuweisung, Unboxing-Zuweisung, Rückgabeanweisungen, Argumente für Methoden und Auslösen von Ausdrücken.
Sie können eine von drei Aktionen ausführen, um diese Warnungen zu beheben. Eine besteht darin, die ?
-Anmerkung hinzuzufügen, um die Variable zu einem Nullable-Verweistyp zu machen. Diese Änderung kann andere Warnungen verursachen. Durch Änderung einer Variablen von einem Non-Nullable-Verweis in einen Nullable-Verweis wird der standardmäßige NULL-Zustand von not-null in maybe-null geändert. Die statische Analyse des Compilers kann Vorkommen finden, in denen Sie eine Variable dereferenzieren, die maybe-null ist.
Die anderen Aktionen weisen den Compiler an, dass die rechte Seite der Zuweisung not-null ist. Der Ausdruck auf der rechten Seite kann vor der Zuweisung auf NULL geprüft werden, wie im folgenden Beispiel gezeigt:
string notNullMsg = TryGetMessage(42) ?? "Unknown message id: 42";
Die obigen Beispiele veranschaulichen die Zuweisung zum Rückgabewert einer Methode. Sie können die Methode (oder Eigenschaft) mit einer Anmerkung versehen, um anzugeben, wann eine Methode einen not-null-Wert zurückgibt. System.Diagnostics.CodeAnalysis.NotNullIfNotNullAttribute gibt häufig an, dass ein Rückgabewert not-null ist, wenn ein Eingabeargument not-null ist. Eine andere Alternative ist das Hinzufügen des NULL-toleranten Operators !
auf der rechten Seite:
string msg = TryGetMessage(42)!;
Zum Beheben einer Warnung für die Zuweisung eines maybe-null-Ausdrucks zu einer not-null-Variablen gibt es vier Techniken:
Dieser Satz von Warnungen benachrichtigt Sie, dass Sie eine Variable mit Non-Nullable-Typ einem Ausdruck zuweisen, dessen NULL-Zustandmaybe-null ist. Diese Warnungen sind:
Betrachten Sie beispielsweise die folgende Klasse:
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
Weder FirstName
noch LastName
werden garantiert initialisiert. Wenn dieser Code neu ist, sollten Sie die öffentliche Schnittstelle ändern. Das obige Beispiel könnte wie folgt aktualisiert werden:
public class Person
{
public Person(string first, string last)
{
FirstName = first;
LastName = last;
}
public string FirstName { get; set; }
public string LastName { get; set; }
}
Wenn Sie vor dem Festlegen des Namens ein Person
-Objekt erstellen müssen, können Sie die Eigenschaften mit einem Non-Null-Standardwert initialisieren:
public class Person
{
public string FirstName { get; set; } = string.Empty;
public string LastName { get; set; } = string.Empty;
}
Eine andere Alternative kann sein, diese Member in Nullable-Verweistypen zu ändern. Die Person
-Klasse könnte wie folgt definiert werden, wenn null
für den Namen zulässig sein soll:
public class Person
{
public string? FirstName { get; set; }
public string? LastName { get; set; }
}
Vorhandener Code erfordert möglicherweise andere Änderungen, um den Compiler über die NULL-Semantik für diese Member zu informieren. Möglicherweise haben Sie mehrere Konstruktoren erstellt, und die Klasse verfügt über eine private Hilfsmethode, die Member initialisiert. Sie können den Initialisierungscode in einen einzelnen Konstruktor verschieben und sicherstellen, dass alle Konstruktoren den Code mit dem gemeinsamen Initialisierungscode aufrufen. Sie können auch die Attribute System.Diagnostics.CodeAnalysis.MemberNotNullAttribute und System.Diagnostics.CodeAnalysis.MemberNotNullWhenAttribute verwenden. Diese Attribute informieren den Compiler darüber, dass ein Member not-null ist, nachdem die Methode aufgerufen wurde. 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";
}
}
Schließlich können Sie den NULL-toleranten Operator verwenden, um anzugeben, dass ein Member in einem anderen Code initialisiert wird. Betrachten Sie für ein weiteres Beispiel die folgenden Klassen, die ein Entity Framework Core-Modell darstellen:
public class TodoItem
{
public long Id { get; set; }
public string? Name { get; set; }
public bool IsComplete { get; set; }
}
public class TodoContext : DbContext
{
public TodoContext(DbContextOptions<TodoContext> options)
: base(options)
{
}
public DbSet<TodoItem> TodoItems { get; set; } = null!;
}
Die DbSet
-Eigenschaft wird mit null!
initialisiert. Dies teilt dem Compiler mit, dass die Eigenschaft auf einen not-null-Wert festgelegt ist. Tatsächlich führt base DbContext
die Set-Initialisierung durch. Die statische Analyse des Compilers greift dies nicht auf. Weitere Informationen zur Verwendung von Nullable-Verweistypen und Entity Framework Core finden Sie im Artikel Arbeiten mit Nullable-Verweistypen in EF Core.
Zum Beheben einer Warnung für die Nicht-Initialisierung eines Non-Nullable-Members gibt es vier Techniken:
null!
hinzu, um anzugeben, dass der Member in einem anderen Code initialisiert wird.Viele Warnungen weisen darauf hin, dass zwischen Signaturen für Methoden, Delegaten oder Typparameter keine Übereinstimmung in Bezug auf die NULL-Zulässigkeit besteht.
Im folgenden Code wird CS8764 veranschaulicht:
public class B
{
public virtual string GetMessage(string id) => string.Empty;
}
public class D : B
{
public override string? GetMessage(string? id) => default;
}
Das obige Beispiel veranschaulicht eine virtual
-Methode in einer Basisklasse und eine override
-Methode mit unterschiedlicher NULL-Zulässigkeit. Die Basisklasse gibt eine Non-Nullable-Zeichenfolge zurück, die abgeleitete Klasse gibt aber eine Nullable-Zeichenfolge zurück. Wenn string
und string?
umgekehrt werden, wäre dies zulässig, da die abgeleitete Klasse restriktiver ist. Ebenso sollten Parameterdeklarationen übereinstimmen. Parameter in der override-Methode können NULL zulassen, auch wenn die Basisklasse dies nicht tut.
In anderen Situationen können diese Warnungen generiert werden. Möglicherweise gibt es einen Konflikt in der Deklaration einer Schnittstellenmethode und der Implementierung dieser Methode. Oder ein Delegattyp und der Ausdruck für diesen Delegat können nicht übereinstimmen. Ein Typparameter und das Typargument können sich in der NULL-Zulässigkeit unterscheiden.
Aktualisieren Sie die entsprechende Deklaration, um diese Warnungen zu beheben.
In den obigen Abschnitten wurde erläutert, wie Sie -Attribute für die statische Nullable-Analyse verwenden können, um den Compiler über die NULL-Semantik Ihres Codes zu informieren. Der Compiler gibt eine Warnung aus, wenn der Code die Zusagen dieses Attributs nicht einhält:
[NotNull]
oder [DisallowNull]
markierten Typ verwendet werden.[DoesNotReturn]
gekennzeichnete Methode darf nicht zurückgegeben werden.[DoesNotReturn]
für den Abgleich mit dem implementierten oder überschriebenen Member.Sehen Sie sich die folgende Methode an:
public bool TryGetMessage(int id, [NotNullWhen(true)] out string? message)
{
message = null;
return true;
}
Der Compiler erzeugt eine Warnung, da der message
-Parameter null
zugewiesen ist, und die Methode true
zurückgibt. Das NotNullWhen
-Attribut gibt an, dass nicht passieren sollte.
Um diese Warnungen zu beheben, aktualisieren Sie Ihren Code so, dass er den Erwartungen der angewendeten Attribute entspricht. Sie können die Attribute oder den Algorithmus ändern.
Switch-Ausdrücke müssen vollständig sein, was bedeutet, dass alle Eingabewerte verarbeitet werden müssen. Auch bei Non-Nullable-Verweistypen muss der null
-Wert berücksichtigt werden. Der Compiler gibt Warnungen aus, wenn der NULL-Wert nicht behandelt wird:
Der folgende Beispielcode veranschaulicht diese Bedingung:
int AsScale(string status) =>
status switch
{
"Red" => 0,
"Yellow" => 5,
"Green" => 10,
{ } => -1
};
Der Eingabeausdruck ist ein string
, kein string?
. Der Compiler generiert diese Warnung weiterhin. Das { }
-Muster behandelt alle Nicht-NULL-Werte, stimmt aber nicht mit null
überein. Um diese Fehler zu beheben, können Sie entweder einen expliziten null
-Fall hinzufügen oder das { }
durch das _
-Muster (Verwerfen) ersetzen. Das Verwerfen-Muster passt sowohl auf Null als auch auf jeden anderen Wert.
Feedback zu .NET
.NET ist ein Open Source-Projekt. Wählen Sie einen Link aus, um Feedback zu geben:
Ereignisse
17. März, 23 Uhr - 21. März, 23 Uhr
Nehmen Sie an der Meetup-Serie teil, um skalierbare KI-Lösungen basierend auf realen Anwendungsfällen mit Mitentwicklern und Experten zu erstellen.
Jetzt registrieren