Поскольку спецификация языка ожидает там выражение типа System.Exception
(следовательно, null
является допустимым в этом контексте) и не ограничивает это выражение ненулевым. В общем, нет способа определить, является ли значение этого выражения null
или нет. Это должно было бы решить проблему остановки. В любом случае среда выполнения будет иметь дело с делом null
. См:
Exception ex = null;
if (conditionThatDependsOnSomeInput)
ex = new Exception();
throw ex;
Конечно, они могли бы сделать конкретный случай отказа от литерала null
недействительным, но это не сильно помогло бы, так зачем тратить пространство спецификации и уменьшать согласованность для небольшой выгоды?
Отказ от ответственности (до того, как Эрик Липперт дал мне пощечину): Это мое собственное предположение о причинах этого дизайнерского решения. Конечно, я не был на совещании дизайнеров;)
Ответ на ваш второй вопрос, может ли когда-либо переменная выражения, пойманная в предложении catch, быть нулевой: хотя в спецификации C # ничего не говорится о том, могут ли другие языки вызывать распространение исключения null
, она определяет способ распространяются исключения:
Предложения catch, если таковые имеются, проверяются в порядке появления, чтобы найти подходящий обработчик для исключения. Первое предложение catch , которое указывает тип исключения или базовый тип типа исключения , считается совпадением. Общее предложение catch считается подходящим для любого типа исключения. [...]
Для null
смелое утверждение ложно. Таким образом, хотя он основан исключительно на том, что говорится в спецификации C #, мы не можем сказать, что базовая среда выполнения никогда не выдаст ноль, но мы можем быть уверены, что даже в этом случае он будет обрабатываться только универсальным catch {}
пункт.
Для реализации C # в CLI мы можем обратиться к спецификации ECMA 335. В этом документе определяются все исключения, которые внутренне генерирует CLI (ни один из которых не является null
), и упоминается, что определенные пользователем объекты исключений генерируются инструкцией throw
. Описание этой инструкции практически идентично оператору C # throw
(за исключением того, что оно не ограничивает тип объекта System.Exception
):
Описание:
Инструкция throw
выбрасывает объект исключения (тип O
) в стек и очищает стек. Подробнее о механизме исключений см. Раздел I.
[Примечание: хотя CLI разрешает выбрасывать любой объект, CLS описывает конкретный класс исключений, который должен использоваться для взаимодействия языков. конечная нота]
Исключения:
System.NullReferenceException
выбрасывается, если obj
равно null
.
Корректность:
Правильный CIL гарантирует, что объект всегда является либо null
, либо ссылкой на объект (т. Е. Типа O
).
Я считаю, что этого достаточно, чтобы сделать заключение, что пойманные исключения никогда не будут null
.