
Es ist kein Geheimnis, dass Microsoft schon seit einiger Zeit an der 8. Version der C # -Sprache arbeitet. Die neue Sprachversion (C # 8.0) ist bereits in der aktuellen Version von Visual Studio 2019 verfügbar, befindet sich jedoch noch in der Beta-Phase. In dieser neuen Version werden einige Funktionen auf etwas nicht offensichtliche oder eher unerwartete Weise implementiert. Nullable Referenztypen sind einer von ihnen. Diese Funktion wird angekündigt, um Null Reference Exceptions (NRE) zu bekämpfen.
Es ist gut zu sehen, wie sich die Sprache weiterentwickelt, und neue Funktionen zu erwerben, um Entwicklern zu helfen. Zufällig haben wir vor einiger Zeit die Fähigkeit des C # -Analysators von PVS-Studio, NREs zu erkennen, erheblich verbessert. Und jetzt fragen wir uns, ob statische Analysegeräte im Allgemeinen und PVS-Studio im Besonderen sich immer noch die Mühe machen sollten, potenzielle Null-Dereferenzen zu diagnostizieren, da solche Dereferenzen zumindest in neuem Code, der Nullable Reference verwendet, "unmöglich" werden. Versuchen wir das zu klären.
Vor- und Nachteile der neuen Funktion
Eine Erinnerung, bevor wir fortfahren: In der neuesten Beta-Version von C # 8.0, die zum Zeitpunkt des Schreibens dieses Beitrags verfügbar ist, sind nullfähige Referenztypen standardmäßig deaktiviert, dh das Verhalten der Referenztypen hat sich nicht geändert.
Was sind also genau nullbare Referenztypen in C # 8.0, wenn wir diese Option aktivieren? Es sind im Grunde die gleichen guten alten Referenztypen, außer dass Sie jetzt '?' nach dem
Typnamen (zum Beispiel
string? ), ähnlich wie
Nullable <T> , d.
h. nullable
Werttypen (zum Beispiel
int? ). Ohne das '?' Wird unser
Zeichenfolgentyp jetzt als nicht nullfähige Referenz interpretiert, d. H. Als Referenztyp, dem keine
Null zugewiesen werden kann.
Die Nullreferenzausnahme ist eine der ärgerlichsten Ausnahmen für Ihr Programm, da sie nicht viel über die Quelle aussagt, insbesondere wenn die Auslösemethode eine Reihe von Dereferenzierungsoperationen hintereinander enthält. Die Möglichkeit, die Zuweisung von Nullen zu einer Variablen eines Referenztyps zu verbieten, sieht cool aus. Was ist jedoch mit den Fällen, in denen das Übergeben einer
Null an eine Methode von einer Ausführungslogik abhängt? Anstelle von
null könnten wir natürlich ein Literal, eine Konstante oder einfach einen "unmöglichen" Wert verwenden, der der Variablen logischerweise nirgendwo anders zugewiesen werden kann. Dies birgt jedoch das Risiko, einen Absturz des Programms durch eine "stille", aber fehlerhafte Ausführung zu ersetzen, was oft schlimmer ist, als sich dem Fehler sofort zu stellen.
Was ist dann mit einer Ausnahme? Eine sinnvolle Ausnahme, die an einem Ort ausgelöst wird, an dem ein
Fehler aufgetreten ist, ist immer besser als ein
NRE irgendwo oben oder unten im Stapel. Aber es ist nur in Ihrem eigenen Projekt gut, wo Sie die Verbraucher korrigieren können, indem Sie einen
Try-Catch- Block einfügen, und es liegt allein in Ihrer Verantwortung. Bei der Entwicklung einer Bibliothek mit (nicht) nullbaren Referenzen müssen wir sicherstellen, dass eine bestimmte Methode immer einen Wert zurückgibt. Schließlich ist es selbst in Ihrem eigenen Code nicht immer möglich (oder zumindest einfach), die Rückgabe von
null durch das Auslösen von Ausnahmen zu ersetzen (da dies möglicherweise zu viel Code betrifft).
Die Nullable-Referenz kann entweder auf globaler Projektebene durch Hinzufügen der
NullableContextOptions- Eigenschaft mit dem Wert
enable oder auf Dateiebene mithilfe der Präprozessor-Direktive
aktiviert werden :
#nullable enable string cantBeNull = string.Empty; string? canBeNull = null; cantBeNull = canBeNull!;
Durch die Nullable-Referenzfunktion werden Typen informativer. Die Methodensignatur gibt Ihnen einen Hinweis auf ihr Verhalten: ob sie eine Nullprüfung hat oder nicht, ob sie
null zurückgeben kann oder nicht. Wenn Sie nun versuchen, eine nullfähige Referenzvariable zu verwenden, ohne sie zu überprüfen, gibt der Compiler eine Warnung aus.
Dies ist sehr praktisch, wenn Sie Bibliotheken von Drittanbietern verwenden, erhöht jedoch auch das Risiko, dass der Benutzer der Bibliothek irregeführt wird, da es immer noch möglich ist, mit dem neuen nullverzeihenden Operator (!) Null zu übergeben. Das heißt, das Hinzufügen nur eines Ausrufezeichens kann alle weiteren Annahmen über die Schnittstelle unter Verwendung solcher Variablen aufheben:
#nullable enable String GetStr() { return _count > 0 ? _str : null!; } String str = GetStr(); var len = str.Length;
Ja, Sie können argumentieren, dass dies eine schlechte Programmierung ist und niemand solchen Code wirklich schreiben würde, aber solange dies möglicherweise möglich ist, können Sie sich nicht sicher fühlen, wenn Sie sich nur auf den Vertrag verlassen, der durch die Schnittstelle einer bestimmten Methode auferlegt wird ( sagen, dass es nicht
null zurückgeben kann ).
Übrigens könnten Sie den gleichen Code mit mehreren schreiben
! Operatoren, wie C # es Ihnen jetzt erlaubt (und dieser Code ist perfekt kompilierbar):
cantBeNull = canBeNull!!!!!!!;
Indem wir so schreiben, betonen wir sozusagen die Idee: "Schau, das kann
null sein !!!" (Wir in unserem Team nennen das "emotionale" Programmierung). Tatsächlich interpretiert der Compiler (aus Roslyn) beim Erstellen des Syntaxbaums das
! Operator auf die gleiche Weise, wie er reguläre Klammern interpretiert, was bedeutet, dass Sie so viele schreiben können
! ist wie du willst - genau wie in Klammern. Aber wenn Sie genug davon schreiben, können Sie den Compiler "niederschlagen". Möglicherweise wird dies in der endgültigen Version von C # 8.0 behoben.
Ebenso können Sie die Compiler-Warnung umgehen, wenn Sie ohne Überprüfung auf eine nullfähige Referenzvariable zugreifen:
canBeNull!.ToString();
Fügen wir weitere Emotionen hinzu:
canBeNull!!!?.ToString();
Eine solche Syntax wird man in echtem Code allerdings kaum jemals sehen. Durch Schreiben des
nullverzeihenden Operators teilen wir dem Compiler mit: "Dieser Code ist in Ordnung, überprüfen Sie, ob er nicht benötigt wird." Durch Hinzufügen des Elvis-Operators sagen wir: „Oder vielleicht auch nicht; Lass es uns für alle Fälle überprüfen. “
Nun können Sie sich vernünftigerweise fragen, warum Variablen mit nicht nullbaren Referenztypen immer noch so einfach
Null zugewiesen werden kann, wenn das Konzept dieses Typs impliziert, dass solche Variablen nicht den Wert
Null haben können . Die Antwort ist, dass "unter der Haube" auf IL-Code-Ebene unser nicht nullbarer Referenztyp immer noch ... der gute alte "reguläre" Referenztyp ist und die gesamte Nullfähigkeitssyntax eigentlich nur eine Anmerkung für den integrierten Compiler ist Analysator (der unserer Meinung nach nicht ganz bequem zu bedienen ist, aber darauf werde ich später näher eingehen). Persönlich finden wir es nicht „ordentlich“, die neue Syntax einfach als Anmerkung für ein Drittanbieter-Tool (sogar in den Compiler integriert) aufzunehmen, da die Tatsache, dass dies nur eine Anmerkung ist, möglicherweise überhaupt nicht offensichtlich ist für den Programmierer, da diese Syntax der Syntax für nullfähige Strukturen sehr ähnlich ist, jedoch auf völlig andere Weise funktioniert.
Zurück zu anderen Möglichkeiten, nullbare Referenztypen zu brechen. Zum Zeitpunkt des Schreibens dieses Artikels, wenn Sie eine Lösung haben, die aus mehreren Projekten besteht, übergeben Sie eine Variable eines Referenztyps, z. B.
String, von einer in einem Projekt deklarierten Methode an eine Methode in einem anderen Projekt mit dem
NullableContext Der Compiler geht davon aus, dass es sich um einen nicht nullbaren String handelt, und der Compiler bleibt stumm. Und das trotz der Unmengen von
[Nullable (1)] - Attributen, die jedem Feld und jeder Methode im IL-Code hinzugefügt wurden, wenn Nullable References aktiviert wurden
. Diese Attribute sollten übrigens berücksichtigt werden, wenn Sie Reflection verwenden, um die Attribute zu verarbeiten, und davon ausgehen, dass der Code nur Ihre benutzerdefinierten Attribute enthält.
Eine solche Situation kann zusätzliche Probleme verursachen, wenn eine große Codebasis an den Nullable Reference-Stil angepasst wird. Dieser Prozess wird wahrscheinlich eine Weile dauern, Projekt für Projekt. Wenn Sie vorsichtig sind, können Sie die neue Funktion natürlich schrittweise integrieren. Wenn Sie jedoch bereits ein funktionierendes Projekt haben, sind Änderungen daran gefährlich und unerwünscht (wenn es funktioniert, berühren Sie es nicht!). Aus diesem Grund haben wir sichergestellt, dass Sie Ihren Quellcode nicht ändern oder markieren müssen, um potenzielle
NREs zu erkennen, wenn Sie den PVS-Studio-Analysator verwenden. Um Standorte zu überprüfen, die eine
NullReferenceException auslösen könnten, führen
Sie einfach den Analysator aus und suchen Sie nach V3080-Warnungen. Sie müssen weder die Projekteigenschaften noch den Quellcode ändern. Sie müssen keine Anweisungen, Attribute oder Operatoren hinzufügen. Legacy-Code muss nicht geändert werden.
Beim Hinzufügen von Nullable Reference-Unterstützung zu PVS-Studio mussten wir entscheiden, ob der Analysator davon ausgehen sollte, dass Variablen von nicht nullbaren Referenztypen immer nicht null Werte haben. Nachdem wir untersucht hatten, wie diese Garantie verletzt werden könnte, entschieden wir, dass PVS-Studio eine solche Annahme nicht treffen sollte. Selbst wenn ein Projekt durchgehend nicht nullfähige Referenztypen verwendet, kann der Analysator diese Funktion ergänzen, indem er bestimmte Situationen erkennt, in denen solche Variablen den Wert
null haben können .
Wie PVS-Studio nach Nullreferenzausnahmen sucht
Die Datenflussmechanismen im C # -Analysator von PVS-Studio verfolgen mögliche Werte von Variablen während des Analyseprozesses. Dies umfasst auch die interprozedurale Analyse, dh das Aufspüren möglicher Werte, die von einer Methode und ihren verschachtelten Methoden zurückgegeben werden, und so weiter. Darüber hinaus speichert PVS-Studio Variablen, denen ein
Nullwert zugewiesen werden könnte. Immer wenn eine solche Variable ohne Prüfung dereferenziert wird, sei es im aktuell analysierten Code oder in einer in diesem Code aufgerufenen Methode, wird eine V3080-Warnung über eine mögliche Nullreferenzausnahme ausgegeben.
Die Idee hinter dieser Diagnose ist, dass der Analysator nur dann wütend wird, wenn er eine
Nullzuweisung sieht. Dies ist der Hauptunterschied zwischen dem Verhalten unserer Diagnose und dem des im Compiler integrierten Analysators, der nullfähige Referenztypen verarbeitet. Der eingebaute Analysator zeigt auf jede Dereferenzierung einer nicht aktivierten nullbaren Referenzvariablen - vorausgesetzt, sie wurde nicht durch die Verwendung von
! Bediener oder auch nur eine komplizierte Überprüfung (es sollte jedoch beachtet werden, dass absolut jeder statische Analysator, wobei PVS-Studio hier keine Ausnahme darstellt, auf die eine oder andere Weise "irregeführt" werden kann, insbesondere wenn Sie dies beabsichtigen).
PVS-Studio hingegen warnt Sie nur, wenn eine
Null angezeigt wird (ob im lokalen Kontext oder im Kontext einer externen Methode). Selbst wenn die Variable von einem nicht nullbaren Referenztyp ist, zeigt der Analysator weiter darauf, wenn dieser Variablen eine Nullzuweisung zugewiesen wird. Wir glauben, dass dieser Ansatz angemessener (oder zumindest für den Benutzer bequemer) ist, da nicht der gesamte Code mit Nullprüfungen "verschmiert" werden muss, um mögliche Dereferenzen zu verfolgen. Schließlich war diese Option bereits vor der Nullable-Referenz verfügbar wurden zum Beispiel durch die Verwendung von Verträgen eingeführt. Darüber hinaus kann der Analysator jetzt die nicht nullbaren Referenzvariablen selbst besser steuern. Wenn eine solche Variable "fair" verwendet wird und niemals
null zugewiesen wird, sagt PVS-Studio kein Wort. Wenn die Variable
null zugewiesen und dann ohne vorherige Überprüfung dereferenziert wird, gibt PVS-Studio eine V3080-Warnung aus:
#nullable enable String GetStr() { return _count > 0 ? _str : null!; } String str = GetStr(); var len = str.Length; <== V3080: Possible null dereference. Consider inspecting 'str'
Schauen wir uns nun einige Beispiele an, die zeigen, wie diese Diagnose durch den Code von Roslyn selbst ausgelöst wird. Wir haben
dieses Projekt bereits kürzlich
überprüft , aber dieses Mal werden wir nur mögliche Nullreferenzausnahmen untersuchen, die in den vorherigen Artikeln nicht erwähnt wurden. Wir werden sehen, wie PVS-Studio potenzielle NREs erkennt und wie sie mithilfe der neuen Nullable Reference-Syntax behoben werden können.
V3080 [CWE-476] Mögliche Null-Dereferenzierung innerhalb der Methode. Überprüfen Sie das zweite Argument: chainedTupleType. Microsoft.CodeAnalysis.CSharp TupleTypeSymbol.cs 244 NamedTypeSymbol chainedTupleType; if (_underlyingType.Arity < TupleTypeSymbol.RestPosition) { .... chainedTupleType = null; } else { .... } return Create(ConstructTupleUnderlyingType(firstTupleType, chainedTupleType, newElementTypes), elementNames: _elementNames);
Wie Sie sehen können, kann der Variablen
chainedTupleType in einem der Ausführungszweige der
Nullwert zugewiesen werden. Es wird dann an die
ConstructTupleUnderlyingType- Methode übergeben und dort nach einer
Debug.Assert- Prüfung verwendet. Es ist ein sehr verbreitetes Muster in Roslyn, aber denken Sie daran, dass
Debug.Assert in der Release-Version entfernt wurde. Aus diesem Grund hält der Analysator die Dereferenzierung innerhalb der
ConstructTupleUnderlyingType- Methode immer noch für gefährlich. Hier ist der Hauptteil dieser Methode, bei der die Dereferenzierung stattfindet:
internal static NamedTypeSymbol ConstructTupleUnderlyingType( NamedTypeSymbol firstTupleType, NamedTypeSymbol chainedTupleTypeOpt, ImmutableArray<TypeWithAnnotations> elementTypes) { Debug.Assert (chainedTupleTypeOpt is null == elementTypes.Length < RestPosition); .... while (loop > 0) { .... currentSymbol = chainedTupleTypeOpt.Construct(chainedTypes); loop--; } return currentSymbol; }
Es ist eigentlich umstritten, ob der Analysator solche Behauptungen berücksichtigen sollte (einige unserer Benutzer möchten dies) - schließlich berücksichtigt der Analysator Verträge von System.Diagnostics.Contracts. Hier ist ein kleines Beispiel aus der Praxis aus unserer Erfahrung mit Roslyn in unserem eigenen Analysegerät. Während wir kürzlich
die Unterstützung der neuesten Version von Visual Studio hinzugefügt haben , haben wir Roslyn auch auf die 3. Version aktualisiert. Danach stürzte PVS-Studio auf bestimmten Code ab, auf dem es noch nie zuvor abgestürzt war. Der Absturz, begleitet von einer Nullreferenzausnahme, würde nicht in unserem Code, sondern im Code von Roslyn auftreten. Das Debuggen ergab, dass das Codefragment, in dem Roslyn jetzt abstürzte,
genau diese Art von
Debug.Assert- basierter
Nullprüfung mehrere Zeilen höher
aufwies - und diese Prüfung hat offensichtlich nicht geholfen.
Es ist ein grafisches Beispiel dafür, wie Sie Probleme mit Nullable Reference bekommen können, da der Compiler
Debug.Assert als zuverlässige Überprüfung in jeder Konfiguration behandelt. Wenn Sie also
#nullable enable hinzufügen und das Argument
chainedTupleTypeOpt als nullfähige Referenz markieren
, gibt der Compiler keine Warnung zur Dereferenzierung innerhalb der
ConstructTupleUnderlyingType- Methode aus.
Fahren Sie mit anderen Beispielen für Warnungen von PVS-Studio fort.
V3080 Mögliche Null-Dereferenzierung. Betrachten Sie die Überprüfung von 'effektivRuleset'. RuleSet.cs 146 var effectiveRuleset = ruleSet.GetEffectiveRuleSet(includedRulesetPaths); effectiveRuleset = effectiveRuleset.WithEffectiveAction(ruleSetInclude.Action); if (IsStricterThan(effectiveRuleset.GeneralDiagnosticOption, ....)) effectiveGeneralOption = effectiveRuleset.GeneralDiagnosticOption;
Diese Warnung besagt, dass der Aufruf der
WithEffectiveAction- Methode möglicherweise
null zurückgibt , während der der Variablen
effektiveRuleset zugewiesene Rückgabewert vor der Verwendung nicht überprüft wird (
effektiveRuleset.GeneralDiagnosticOption ). Hier ist der Hauptteil der
WithEffectiveAction- Methode:
public RuleSet WithEffectiveAction(ReportDiagnostic action) { if (!_includes.IsEmpty) throw new ArgumentException(....); switch (action) { case ReportDiagnostic.Default: return this; case ReportDiagnostic.Suppress: return null; .... return new RuleSet(....); default: return null; } }
Wenn Nullable Reference für die Methode
GetEffectiveRuleSet aktiviert ist , erhalten wir zwei Stellen, an denen das Verhalten des Codes geändert werden muss. Da die oben gezeigte Methode eine Ausnahme auslösen kann, ist es logisch anzunehmen, dass der Aufruf in einen
Try-Catch- Block eingeschlossen ist, und es wäre richtig, die Methode neu zu schreiben, um eine Ausnahme auszulösen, anstatt
null zurückzugeben . Wenn Sie jedoch einige Anrufe zurückverfolgen, werden Sie feststellen, dass der Fangcode zu weit oben ist, um die Konsequenzen zuverlässig vorherzusagen.
Werfen wir einen Blick auf den Konsumenten der
effektivenRuleset- Variablen, der
IsStricterThan- Methode:
private static bool IsStricterThan(ReportDiagnostic action1, ReportDiagnostic action2) { switch (action2) { case ReportDiagnostic.Suppress: ....; case ReportDiagnostic.Warn: return action1 == ReportDiagnostic.Error; case ReportDiagnostic.Error: return false; default: return false; } }
Wie Sie sehen können, handelt es sich um eine einfache switch-Anweisung, die zwischen zwei Aufzählungen mit
ReportDiagnostic.Default als Standardwert wählt. Schreiben Sie den Anruf am besten wie folgt um:
Die Signatur von
WithEffectiveAction ändert sich:
#nullable enable public RuleSet? WithEffectiveAction(ReportDiagnostic action)
So sieht der Anruf aus:
RuleSet? effectiveRuleset = ruleSet.GetEffectiveRuleSet(includedRulesetPaths); effectiveRuleset = effectiveRuleset?.WithEffectiveAction(ruleSetInclude.Action); if (IsStricterThan(effectiveRuleset?.GeneralDiagnosticOption ?? ReportDiagnostic.Default, effectiveGeneralOption)) effectiveGeneralOption = effectiveRuleset.GeneralDiagnosticOption;
Da
IsStricterThan nur einen Vergleich durchführt, kann die Bedingung neu geschrieben werden - zum Beispiel wie
folgt :
if (effectiveRuleset == null || IsStricterThan(effectiveRuleset.GeneralDiagnosticOption, effectiveGeneralOption))
Nächstes Beispiel.
V3080 Mögliche Null-Dereferenzierung. Überprüfen Sie 'propertySymbol'. BinderFactory.BinderFactoryVisitor.cs 372 var propertySymbol = GetPropertySymbol(parent, resultBinder); var accessor = propertySymbol.GetMethod; if ((object)accessor != null) resultBinder = new InMethodBinder(accessor, resultBinder);
Um diese Warnung zu beheben, müssen wir sehen, was als nächstes mit der
Eigenschaft propertySymbol passiert.
private SourcePropertySymbol GetPropertySymbol( BasePropertyDeclarationSyntax basePropertyDeclarationSyntax, Binder outerBinder) { .... NamedTypeSymbol container = GetContainerType(outerBinder, basePropertyDeclarationSyntax); if ((object)container == null) return null; .... return (SourcePropertySymbol)GetMemberSymbol(propertyName, basePropertyDeclarationSyntax.Span, container, SymbolKind.Property); }
Auch die
GetMemberSymbol- Methode kann unter bestimmten Bedingungen
null zurückgeben .
private Symbol GetMemberSymbol( string memberName, TextSpan memberSpan, NamedTypeSymbol container, SymbolKind kind) { foreach (Symbol sym in container.GetMembers(memberName)) { if (sym.Kind != kind) continue; if (sym.Kind == SymbolKind.Method) { .... var implementation = ((MethodSymbol)sym).PartialImplementationPart; if ((object)implementation != null) if (InSpan(implementation.Locations[0], this.syntaxTree, memberSpan)) return implementation; } else if (InSpan(sym.Locations, this.syntaxTree, memberSpan)) return sym; } return null; }
Wenn nullbare Referenztypen aktiviert sind, ändert sich der Aufruf wie folgt:
#nullable enable SourcePropertySymbol? propertySymbol = GetPropertySymbol(parent, resultBinder); MethodSymbol? accessor = propertySymbol?.GetMethod; if ((object)accessor != null) resultBinder = new InMethodBinder(accessor, resultBinder);
Es ist ziemlich einfach zu beheben, wenn Sie wissen, wo Sie suchen müssen. Die statische Analyse kann diesen potenziellen Fehler ohne Aufwand erfassen, indem alle möglichen Werte des Felds aus allen Prozeduraufrufketten erfasst werden.
V3080 Mögliche Null-Dereferenzierung. Überprüfen Sie 'simpleName'. CSharpCommandLineParser.cs 1556 string simpleName; simpleName = PathUtilities.RemoveExtension( PathUtilities.GetFileName(sourceFiles.FirstOrDefault().Path)); outputFileName = simpleName + outputKind.GetDefaultExtension(); if (simpleName.Length == 0 && !outputKind.IsNetModule()) ....
Das Problem liegt in der Zeile mit der Prüfung
simpleName.Length . Die Variable
simpleName ergibt sich aus der Ausführung einer langen Reihe von Methoden und kann
null zugewiesen werden. Wenn Sie neugierig sind, können Sie sich
übrigens die
RemoveExtension- Methode
ansehen , um zu sehen, wie sie sich von
Path.GetFileNameWithoutExtension unterscheidet. Eine
Prüfung mit simpleName! = Null würde ausreichen, aber bei nicht nullbaren Referenztypen ändert sich der Code wie folgt:
#nullable enable public static string? RemoveExtension(string path) { .... } string simpleName;
So könnte der Anruf aussehen:
simpleName = PathUtilities.RemoveExtension( PathUtilities.GetFileName(sourceFiles.FirstOrDefault().Path)) ?? String.Empty;
Fazit
Nullable Referenztypen können eine große Hilfe sein, wenn Sie die Architektur von Grund auf neu entwerfen. Die Überarbeitung des vorhandenen Codes kann jedoch viel Zeit und Sorgfalt erfordern, da dies zu einer Reihe schwer fassbarer Fehler führen kann. Dieser Artikel soll Sie nicht davon abhalten, nullfähige Referenztypen zu verwenden. Wir finden diese neue Funktion im Allgemeinen nützlich, auch wenn die genaue Art und Weise ihrer Implementierung möglicherweise umstritten ist.
Denken Sie jedoch immer an die Einschränkungen dieses Ansatzes und denken Sie daran, dass das Aktivieren des Nullable Reference-Modus Sie nicht vor NREs schützt und dass es bei Missbrauch selbst zur Quelle dieser Fehler werden kann. Wir empfehlen, dass Sie die Nullable Reference-Funktion durch ein modernes statisches Analysetool wie PVS-Studio ergänzen, das die interprozedurale Analyse unterstützt, um Ihr Programm vor NREs zu schützen. Jeder dieser Ansätze - tiefgreifende interprozedurale Analyse und Annotation von Methodensignaturen (was im Nullable Reference-Modus tatsächlich der Fall ist) - hat seine Vor- und Nachteile. Der Analysator stellt Ihnen eine Liste potenziell gefährlicher Orte zur Verfügung und zeigt Ihnen die Konsequenzen der Änderung des vorhandenen Codes. Wenn irgendwo eine Nullzuweisung vorliegt, zeigt der Analysator auf jeden Verbraucher der Variablen, wo sie ohne Prüfung dereferenziert wird.
Sie können dieses Projekt oder Ihre eigenen Projekte auf andere Fehler überprüfen -
laden Sie einfach PVS-Studio
herunter und probieren Sie es aus.