Ponieważ specyfikacja języka oczekuje tam wyrażenia typu System.Exception(w związku z tym nulljest poprawna w tym kontekście) i nie ogranicza tego wyrażenia do wartości innej niż null. Ogólnie rzecz biorąc, nie ma możliwości wykrycia, czy wartość tego wyrażenia jest, nullczy nie. Musiałby rozwiązać problem zatrzymania. Środowisko wykonawcze i tak będzie musiało zająć się nullsprawą. Widzieć:
Exception ex = null;
if (conditionThatDependsOnSomeInput)
ex = new Exception();
throw ex;
Mogliby oczywiście uczynić konkretny przypadek odrzucenia nulldosłownego nieważnym, ale to niewiele by pomogło, więc po co marnować miejsce na specyfikację i zmniejszać spójność z niewielkimi korzyściami?
Zastrzeżenie (zanim zostanie uderzony przez Erica Lipperta): To jest moja własna spekulacja na temat uzasadnienia tej decyzji projektowej. Oczywiście nie byłem na spotkaniu projektowym;)
Odpowiedź na drugie pytanie, czy zmienna wyrażenia przechwycona w klauzuli catch może kiedykolwiek mieć wartość null: Podczas gdy specyfikacja C # milczy na temat tego, czy inne języki mogą powodować nullpropagowanie wyjątku, definiuje sposób propagowania wyjątków:
Klauzule catch, jeśli istnieją, są sprawdzane w kolejności pojawiania się, aby zlokalizować odpowiednią procedurę obsługi wyjątku. Pierwsza klauzula catch, która określa typ wyjątku lub typ podstawowy typu wyjątku, jest uważana za dopasowanie. Ogólna klauzula catch jest uważana za dopasowanie dla dowolnego typu wyjątku. […]
Bo nullpogrubione stwierdzenie jest fałszywe. Tak więc, chociaż opiera się wyłącznie na tym, co mówi specyfikacja C #, nie możemy powiedzieć, że bazowe środowisko wykonawcze nigdy nie zwróci wartości null, możemy być pewni, że nawet jeśli tak jest, będzie to obsługiwane tylko przez catch {}klauzulę ogólną .
W przypadku implementacji języka C # w interfejsie CLI możemy odwołać się do specyfikacji ECMA 335. Ten dokument definiuje wszystkie wyjątki, które CLI zgłasza wewnętrznie (z których żaden nie jest null) i wspomina, że obiekty wyjątków zdefiniowane przez użytkownika są generowane przez throwinstrukcję. Opis tej instrukcji jest praktycznie identyczny z throwinstrukcją C # (z wyjątkiem tego, że nie ogranicza typu obiektu do System.Exception):
Opis:
throwInstrukcja zgłasza wyjątek (typ obiektu O) w stos i opróżnia stos. Aby uzyskać szczegółowe informacje na temat mechanizmu wyjątków, patrz Partycja I.
[Uwaga: Podczas gdy CLI pozwala na wyrzucenie dowolnego obiektu, CLS opisuje konkretną klasę wyjątku, która powinna być używana do współdziałania języków. notatka końcowa]
Wyjątki:
System.NullReferenceExceptionjest wyrzucany, jeśli objjest null.
Poprawność:
Prawidłowy CIL zapewnia, że obiekt jest zawsze albo nullodwołaniem do obiektu (tj. Typu O).
Uważam, że są one wystarczające, aby stwierdzić, że wychwycone wyjątki nigdy nie są null.