Da die Sprachspezifikation dort einen Ausdruck vom Typ erwartet System.Exception(daher nullin 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 ist nulloder nicht. Es müsste das Halteproblem lösen. Die Laufzeit muss sich nullsowieso mit dem Fall befassen . Sehen:
Exception ex = null;
if (conditionThatDependsOnSomeInput)
ex = new Exception();
throw ex;
Sie könnten natürlich den speziellen Fall, das nullLiteral 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 nullkeine 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:
Die etwaigen catch-Klauseln werden in der Reihenfolge ihres Auftretens geprüft, um einen geeigneten Handler für die Ausnahme zu finden. Die erste catch-Klausel , die den Ausnahmetyp oder einen Basistyp des Ausnahmetyps angibt, wird als Übereinstimmung betrachtet. Eine allgemeine catch-Klausel gilt als Übereinstimmung für jeden Ausnahmetyp. [...]
Denn nulldie 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 generischen catch {}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 der throwAnweisung 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änkt System.Exception):
Beschreibung:
Die throwAnweisung wirft das Ausnahmeobjekt (Typ O) auf den Stapel und leert den Stapel. Einzelheiten zum Ausnahmemechanismus finden Sie unter Partition I.
[Hinweis: Während die CLI das Auslösen von Objekten zulässt, beschreibt die CLS eine bestimmte Ausnahmeklasse, die für die Sprachinteroperabilität verwendet werden soll. Endnote]
Ausnahmen:
System.NullReferenceExceptionwird geworfen wenn objist null.
Richtigkeit:
Durch die korrekte CIL wird sichergestellt, dass das Objekt immer entweder nulloder eine Objektreferenz (dh vom Typ O) ist.
Ich glaube, diese reichen aus, um zu dem Schluss zu kommen, dass es keine Ausnahmen gibt null.