Оскільки специфікація мови очікує там виразу типу System.Exception(отже, nullє допустимим у цьому контексті) і не обмежує цей вираз ненульовим. Загалом, жодним чином він не може визначити, чи є значення цього виразу nullчи ні. Це повинно було б вирішити проблему зупинки. Виконавцю все nullодно доведеться розібратися зі справою. Подивитися:
Exception ex = null;
if (conditionThatDependsOnSomeInput)
ex = new Exception();
throw ex;
Звичайно, вони могли б зробити конкретний випадок викидання nullлітералу недійсним, але це не допомогло б, то навіщо витрачати специфікаційний простір і зменшувати узгодженість з малою користю?
Застереження (до того, як Ерік Ліпперт отримає мене ляпас): Це моє власне припущення щодо міркувань, що лежать в основі цього дизайнерського рішення. Звичайно, я не був на зустрічі дизайнерів;)
Відповідь на ваше друге запитання, чи може змінна виразу, зафіксована в реченні catch, коли-небудь бути нульовою: Хоча специфікація C # мовчить про те, чи можуть інші мови спричинити nullрозповсюдження винятку, вона визначає спосіб розповсюдження винятків:
Застереження про вилов, якщо такі є, перевіряються з метою виявлення відповідного обробника для виключення. Перше речення catch, яке вказує тип виключення або базовий тип типу виключення , вважається збігом. Загальне речення catch вважається збігом для будь-якого типу винятків. [...]
Адже nullжирне твердження хибне. Отже, хоча суто на основі того, що сказано в специфікації C #, ми не можемо сказати, що основний час виконання ніколи не буде видавати null, ми можемо бути впевнені, що навіть якщо це так, це буде оброблятися лише загальним 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.