Wir führen ein System ein und manchmal kommt die berühmte Ausnahme NullReferenceException
bei der Meldung vor Object reference not set to an instance of an object
.
In einer Methode mit fast 20 Objekten ist das Vorhandensein eines Protokolls, das besagt, dass ein Objekt null ist, überhaupt nicht von Nutzen. Es ist, als ob Sie als Sicherheitsbeamter eines Seminars sagen, dass ein Mann unter 100 Teilnehmern ein Terrorist ist. Das nützt dir wirklich gar nichts. Sie sollten mehr Informationen erhalten, wenn Sie feststellen möchten, welcher Mann der bedrohliche Mann ist.
Wenn wir den Fehler entfernen möchten, müssen wir auch wissen, welches Objekt null ist.
Nun, seit einigen Monaten ist mir etwas durch den Kopf gegangen, und das ist:
Warum gibt .NET nicht den Namen oder zumindest den Typ der Objektreferenz an, der null ist? . Kann es den Typ nicht aus der Reflexion oder einer anderen Quelle verstehen?
Was sind die Best Practices, um zu verstehen, welches Objekt null ist? Sollten wir die Nullfähigkeit von Objekten in diesen Kontexten immer manuell testen und das Ergebnis protokollieren? Gibt es einen besseren Weg?
Update:
Die Ausnahme The system cannot find the file specified
hat den gleichen Charakter. Sie können die Datei erst finden, wenn Sie sie an den Prozess anhängen und debuggen. Ich denke, diese Art von Ausnahmen kann intelligenter werden. Wäre es nicht besser, wenn .NET uns c:\temp.txt doesn't exist.
anstelle dieser allgemeinen Nachricht Bescheid geben könnte ? Als Entwickler stimme ich ja.
quelle
new
zum Erstellen von Instanzen einer Klasse enthält. Wann hilft so ein Hinweis wirklich?Antworten:
Das
NullReferenceException
sagt Ihnen im Grunde: Sie machen es falsch. Nicht mehr, nicht weniger. Im Gegenteil, es ist kein vollwertiges Debugging-Tool. In diesem Fall würde ich sagen, dass Sie beides falsch machen, weilIch bin ein großer Fan davon, alles zu überprüfen, bevor etwas schief geht, und dem Entwickler gute Informationen zu liefern. Kurzum: Schreiben Sie Schecks mit
ArgumentNullException
und Likes und schreiben Sie den Namen selbst. Hier ist ein Beispiel:Sie könnten auch in aussehen - Code Contracts , es hat es Macken , aber es funktioniert ziemlich gut und spart Tipparbeit .
quelle
I only say that checking every object to get sure that it's not null, is not a good method
Ernsthaft. Es ist die beste Methode. Und nicht nur null, überprüfen Sie jedes Argument auf sinnvolle Werte. Je früher Sie Fehler abfangen, desto leichter ist die Ursache zu finden. Sie möchten nicht mehrere Ebenen im Stack-Trace zurückverfolgen müssen, um den verursachenden Aufruf zu finden.Es sollte wirklich genau zeigen, was Sie anrufen möchten. Es ist so, als würde man sagen: "Es gibt ein Problem. Sie müssen es beheben. Ich weiß, was es ist. Ich werde es Ihnen nicht sagen. Sie finden es heraus."
Wie nützlich wäre es zum Beispiel, wenn Sie Folgendes hätten ...
...? Um in den Code einzusteigen, ihn durchzuarbeiten und herauszufinden, dass das, was Sie aufrufen
null
möchten, in Ordnung ist, geben Sie uns doch einfach eine kleine Hilfe.Ich bin damit einverstanden, dass es normalerweise nützlich ist, den Code durchzugehen, um zur Antwort zu gelangen (da Sie wahrscheinlich mehr herausfinden werden), aber oftmals würde viel Zeit und Frustration gespart, wenn der
NullReferenceException
Text dem obigen Beispiel ähnlicher wäre.Ich sag bloß.
quelle
KeyNotFoundException
und viele andere Ärgernisse sagen ...Ihr Protokoll sollte einen Stack-Trace enthalten, der normalerweise einen Hinweis darauf gibt, in welcher Zeile der Methode das Problem auftritt. Möglicherweise müssen Sie dafür sorgen, dass Ihr Release-Build PDB-Symbole enthält, damit Sie eine Vorstellung davon haben, in welcher Zeile sich der Fehler befindet.
Zugegeben, es wird dir in diesem Fall nicht helfen:
Das Tell-Don't-Ask- Prinzip kann helfen, solchen Code zu vermeiden.
Ich bin mir nicht sicher, warum die Informationen nicht enthalten sind. Ich vermute, dass sie es zumindest in einem Debug-Build herausfinden könnten, wenn sie es wirklich wollten. Das Erstellen eines Absturzabbilds und das Öffnen in WinDBG kann hilfreich sein.
quelle
Es wurden Ausnahmen erstellt, um außergewöhnliche, nicht tödliche Zustände in der Aufrufkette zu signalisieren . Das heißt, sie sind nicht als Debugging-Tool konzipiert.
Wenn eine Nullzeiger-Ausnahme ein Debugging-Tool wäre, würde sie die Programmausführung sofort abbrechen, sodass ein Debugger eine Verbindung herstellen und direkt auf die belastende Zeile zeigen kann. Dies würde dem Programmierer alle verfügbaren Kontextinformationen geben . (Das ist ziemlich genau das, was ein Segfault aufgrund eines Nullzeigerzugriffs in C macht, wenn auch etwas grob.)
Die Nullzeigerausnahme ist jedoch als gültige Laufzeitbedingung konzipiert, die im normalen Programmablauf ausgelöst und abgefangen werden kann. Folglich müssen Leistungsüberlegungen berücksichtigt werden. Bei jeder Anpassung der Ausnahmebedingungsnachricht müssen Zeichenfolgenobjekte zur Laufzeit erstellt, verkettet und zerstört werden. Somit ist eine statische Nachricht unbestreitbar schneller.
Ich sage aber nicht, dass die Laufzeit nicht so programmiert werden konnte, dass der Name der belastenden Referenz angezeigt würde. Das könnte gemacht werden. Es würde Ausnahmen nur noch langsamer machen als sie sind. Wenn es irgendjemand interessiert, könnte eine solche Funktion sogar umschaltbar gemacht werden, damit der Produktionscode nicht verlangsamt wird, sondern das Debuggen vereinfacht wird. aber aus irgendeinem Grund scheint sich niemand genug darum gekümmert zu haben.
quelle
Ich denke, Cromulent trifft den Nagel auf den Kopf, aber es gibt auch den offensichtlichen Punkt, dass
NullReferenceException
Sie nicht initialisierte Variablen haben , wenn Sie eine erhalten . Das Argument, dass Sie ungefähr 20 Objekte an eine Methode übergeben haben, kann nicht als Milderung bezeichnet werden: Als Ersteller eines Codeblocks müssen Sie für deren Ausführung verantwortlich sein, einschließlich der Konformität mit dem Rest einer Codebasis wie sowie ordnungsgemäße und korrekte Verwendung von Variablen usw.es ist lästig, mühsam und manchmal langweilig, aber die Belohnungen am Ende sind es wert: In vielen Fällen musste ich Protokolldateien mit einem Gewicht von mehreren Gigabyte durchsuchen, und sie sind fast immer hilfreich. Bevor Sie jedoch zu dieser Phase gelangen, kann Ihnen der Debugger helfen, und vor dieser Phase erspart eine gute Planung viel Schmerz (und ich meine auch keine ausgereifte Herangehensweise an Ihre Codelösung: Einfache Skizzen und einige Notizen können und werden besser sein als nichts).
In Bezug auf den
Object reference not set to an instance of an object
Code können wir keine Werte erraten, die uns gefallen könnten: Das ist unsere Aufgabe als Programmierer, und es bedeutet einfach, dass Sie eine nicht initialisierte Variable übergeben haben.quelle
Erfahren Sie, wie Sie den Debugger verwenden. Dies ist genau das, wofür es entwickelt wurde. Setzen Sie einen Haltepunkt für die betreffende Methode und los geht's.
Gehen Sie einfach Ihren Code durch und sehen Sie genau, welche Werte alle Ihre Variablen an bestimmten Punkten haben.
Edit: Ehrlich gesagt bin ich schockiert, dass noch niemand die Verwendung des Debuggers erwähnt hat.
quelle
Wenn Sie die Antwort von @ stijn befolgen und den Code auf Null setzen möchten, sollte dieses Code-Snippet hilfreich sein. Hier finden Sie einige Informationen zu Code-Snippets . Sobald Sie dies eingerichtet haben, geben Sie einfach ein
argnull
, drücken Sie zweimal die Tabulatortaste und füllen Sie dann die Lücke aus.quelle
nameof
dass Ihr Snippetthrow new ArgumentNullException(nameof($argument$))
keine magischen Konstanten mehr enthält, vom Compiler überprüft wird und besser mit Refactoring-Tools