Perché la specifica del linguaggio richiede un'espressione di tipo System.Exception(quindi nullè valida in quel contesto) e non limita questa espressione a non essere nulla. In generale, non è possibile rilevare se il valore di quell'espressione è nullo meno. Dovrebbe risolvere il problema dell'arresto. Il runtime dovrà nullcomunque occuparsi del caso. Vedere:
Exception ex = null;
if (conditionThatDependsOnSomeInput)
ex = new Exception();
throw ex;
Potrebbero, ovviamente, rendere nullinvalido il caso specifico di gettare il letterale, ma ciò non aiuterebbe molto, quindi perché sprecare lo spazio delle specifiche e ridurre la coerenza con poco vantaggio?
Disclaimer (prima di essere schiaffeggiato da Eric Lippert): questa è la mia speculazione sul ragionamento alla base di questa decisione progettuale. Ovviamente non ho partecipato alla riunione di progettazione;)
La risposta alla tua seconda domanda, se una variabile di espressione catturata all'interno di una clausola catch può mai essere nulla: mentre la specifica C # nullnon dice se altri linguaggi possono causare la propagazione di un'eccezione, definisce il modo in cui vengono propagate le eccezioni:
Le clausole catch, se presenti, vengono esaminate in ordine di apparizione per individuare un gestore adatto per l'eccezione. La prima clausola catch che specifica il tipo di eccezione o un tipo di base del tipo di eccezione è considerata una corrispondenza. Una clausola catch generale è considerata una corrispondenza per qualsiasi tipo di eccezione. [...]
Perché nulll'affermazione in grassetto è falsa. Quindi, sebbene basandosi esclusivamente su ciò che dice la specifica C #, non possiamo dire che il runtime sottostante non genererà mai null, possiamo essere sicuri che anche se questo è il caso, sarà gestito solo dalla catch {}clausola generica .
Per le implementazioni C # sulla CLI, possiamo fare riferimento alla specifica ECMA 335. Quel documento definisce tutte le eccezioni che la CLI genera internamente (nessuna delle quali lo è null) e menziona che gli oggetti eccezione definiti dall'utente vengono lanciati throwdall'istruzione. La descrizione di tale istruzione è praticamente identica all'istruzione C # throw(tranne per il fatto che non limita il tipo di oggetto a System.Exception):
Descrizione:
L' throwistruzione lancia l'oggetto eccezione (tipo O) sullo stack e svuota lo stack. Per i dettagli sul meccanismo di eccezione, vedere la partizione I.
[Nota: sebbene la CLI consenta il lancio di qualsiasi oggetto, la CLS descrive una classe di eccezione specifica che deve essere utilizzata per l'interoperabilità del linguaggio. nota finale]
Eccezioni:
System.NullReferenceExceptionviene lanciato se objè null.
Correttezza:
Il CIL corretto garantisce che l'oggetto sia sempre nullo un riferimento a un oggetto (cioè di tipo O).
Credo che questi siano sufficienti per concludere che le eccezioni colte non lo sono mai null.