Beim Schreiben eines besonders komplexen Codes für die Ausnahmebehandlung hat jemand gefragt, ob Sie nicht sicherstellen müssen, dass Ihr Ausnahmeobjekt nicht null ist. Und ich sagte natürlich nicht, entschied mich dann aber, es zu versuchen. Anscheinend können Sie null werfen, aber es wird immer noch irgendwo zu einer Ausnahme.
Warum ist das erlaubt?
throw null;
In diesem Ausschnitt ist 'ex' zum Glück nicht null, aber könnte es jemals sein?
try
{
throw null;
}
catch (Exception ex)
{
//can ex ever be null?
//thankfully, it isn't null, but is
//ex is System.NullReferenceException
}
c#
exception-handling
witzeln
quelle
quelle
throw
eine Anweisung, deren Zweck darin besteht, überhaupt eine Ausnahme auszulösen , bringt eine Warnung nicht viel Wert.Antworten:
Da die Sprachspezifikation dort einen Ausdruck vom Typ erwartet
System.Exception
(dahernull
in diesem Kontext gültig ist) und diesen Ausdruck nicht auf Nicht-Null beschränkt. Im Allgemeinen kann nicht festgestellt werden, ob der Wert dieses Ausdrucks istnull
oder nicht. Es müsste das Halteproblem lösen. Die Laufzeit muss sichnull
sowieso mit dem Fall befassen . Sehen:Sie könnten natürlich den speziellen Fall, das
null
Literal ungültig zu machen, ungültig machen, aber das würde nicht viel helfen. Warum also Spezifikationsraum verschwenden und die Konsistenz für wenig Nutzen reduzieren?Haftungsausschluss (bevor ich von Eric Lippert geschlagen werde): Dies ist meine eigene Spekulation über die Gründe für diese Designentscheidung. Natürlich war ich nicht im Designtreffen;)
Die Antwort auf Ihre zweite Frage, ob eine in einer catch-Klausel abgefangene Ausdrucksvariable jemals null sein kann: Während die C # -Spezifikation
null
keine Aussage darüber enthält, ob andere Sprachen die Weitergabe einer Ausnahme verursachen können , definiert sie die Art und Weise, wie Ausnahmen weitergegeben werden:Denn
null
die fette Aussage ist falsch. Obwohl dies nur auf den Aussagen der C # -Spezifikation basiert, können wir nicht sagen, dass die zugrunde liegende Laufzeit niemals null auslösen wird. Wir können jedoch sicher sein, dass selbst wenn dies der Fall ist, dies nur von der generischencatch {}
Klausel behandelt wird.Für C # -Implementierungen auf der CLI können wir auf die ECMA 335-Spezifikation verweisen. In diesem Dokument werden alle Ausnahmen definiert, die die CLI intern auslöst (keine davon
null
), und es wird erwähnt, dass benutzerdefinierte Ausnahmeobjekte von derthrow
Anweisung ausgelöst werden . Die Beschreibung für diese Anweisung ist praktisch identisch mit der C #throw
-Anweisung (außer dass sie den Typ des Objekts nicht auf Folgendes beschränktSystem.Exception
):Ich glaube, diese reichen aus, um zu dem Schluss zu kommen, dass es keine Ausnahmen gibt
null
.quelle
throw null;
.catch { }
Klausel abzufangen.throw
dessen Argument ein Nullwert sein könnte, würde dies nicht bedeuten, dassthrow null
dies legal sein müsste. Ein Compiler könnte darauf bestehen, dass einthrow
Argument einen erkennbaren Klassentyp hat. Ein Ausdruck wie(System.InvalidOperationException)null
sollte zur Kompilierungszeit gültig sein (das Ausführen sollte a verursachenNullReferenceException
), aber das bedeutet nicht, dass ein untypisierter Ausdrucknull
akzeptabel sein sollte.Der Versuch, ein
null
Objekt zu werfen, führt zu einer (völlig unabhängigen) Nullreferenzausnahme.Zu fragen, warum du werfen darfst,
null
ist wie zu fragen, warum du das tun darfst:quelle
Von hier genommen :
quelle
Während es möglicherweise nicht möglich ist, null in C # zu werfen, weil der Wurf dies erkennt und es in eine NullReferenceException verwandelt, ist es möglich, null zu empfangen ... Ich erhalte das gerade, was meinen Fang verursacht (was nicht der Fall war) erwartet, dass 'ex' null ist), um eine Nullreferenzausnahme zu erfahren, die dann dazu führt, dass meine App stirbt (da dies der letzte Haken war).
Während wir also keine Null aus C # werfen können, kann die Unterwelt null werfen, sodass Ihr äußerster Fang (Ausnahme ex) besser darauf vorbereitet ist, ihn zu empfangen. Nur zur Info.
quelle
Ich denke, vielleicht können Sie nicht - wenn Sie versuchen, null zu werfen, kann es nicht, also tut es, was es sollte, in einem Fehlerfall, der eine Nullreferenzausnahme auslöst. Sie werfen also nicht die Null, sondern die Null nicht, was zu einem Wurf führt.
quelle
Der Versuch zu antworten "..dankbar 'ex' ist nicht null, aber könnte es jemals sein?":
Da wir wohl keine Ausnahmen auslösen können, die null sind, muss eine catch-Klausel auch niemals eine Ausnahme abfangen, die null ist. Somit könnte ex niemals null sein.
Ich sehe jetzt , dass diese Frage in der Tat wurde bereits gefragt .
quelle
throw null
. Dies löst jedoch keine Ausnahme aus, die null ist . Dathrow null
versucht wird, Methoden für eine Nullreferenz aufzurufen, wird die Laufzeit anschließend gezwungen, eine Nicht-Null-Instanz von auszulösenNullReferenceException
.Denken Sie daran, dass eine Ausnahme Details darüber enthält, wo die Ausnahme ausgelöst wird. Da der Konstruktor keine Ahnung hat, wohin er geworfen werden soll, ist es nur sinnvoll, dass die throw-Methode diese Details an dem Punkt in das Objekt einfügt, an dem der Wurf erfolgt. Mit anderen Worten, die CLR versucht, Daten in null einzufügen, wodurch eine NullReferenceException ausgelöst wird.
Ich bin mir nicht sicher, ob genau das passiert, aber es erklärt das Phänomen.
Angenommen, dies ist wahr (und ich kann mir keinen besseren Weg vorstellen, um ex auf null zu bringen, als null zu werfen;), würde dies bedeuten, dass ex unmöglich null sein kann.
quelle
In älteren c #:
Betrachten Sie diese Syntax:
Ich denke, es ist viel kürzer als das:
quelle