Оскільки специфікація мови очікує там виразу типу 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
.