Porque la especificación del lenguaje espera una expresión de tipo System.Exception
allí (por lo tanto, null
es válida en ese contexto) y no restringe esta expresión para que no sea nula. En general, no hay forma de que pueda detectar si el valor de esa expresión es null
o no. Tendría que resolver el problema de la detención. El tiempo de ejecución tendrá que ocuparse del null
caso de todos modos. Ver:
Exception ex = null;
if (conditionThatDependsOnSomeInput)
ex = new Exception();
throw ex;
Por supuesto, podrían hacer que el caso específico de arrojar lo null
literal sea inválido, pero eso no ayudaría mucho, entonces, ¿por qué desperdiciar espacio de especificación y reducir la consistencia para obtener pocos beneficios?
Descargo de responsabilidad (antes de que Eric Lippert me abofetee): esta es mi propia especulación sobre el razonamiento detrás de esta decisión de diseño. Por supuesto, no he estado en la reunión de diseño;)
La respuesta a su segunda pregunta, si una variable de expresión capturada dentro de una cláusula catch puede ser nula alguna vez: si bien la especificación de C # null
no dice nada sobre si otros lenguajes pueden hacer que se propague una excepción, define la forma en que se propagan las excepciones:
Las cláusulas de captura, si las hay, se examinan en orden de aparición para localizar un manejador adecuado para la excepción. La primera cláusula catch que especifica el tipo de excepción o un tipo base del tipo de excepción se considera una coincidencia. Una cláusula catch general se considera una coincidencia para cualquier tipo de excepción. [...]
Porque null
, la declaración en negrita es falsa. Entonces, si bien se basa puramente en lo que dice la especificación C #, no podemos decir que el tiempo de ejecución subyacente nunca arrojará un valor nulo, podemos estar seguros de que incluso si ese es el caso, solo lo manejará el genéricocatch {}
cláusula .
Para las implementaciones de C # en la CLI, podemos consultar la especificación ECMA 335. Ese documento define todas las excepciones que la CLI lanza internamente (ninguna de las cuales lo es null
) y menciona que los objetos de excepción definidos por el usuario son lanzados por la throw
instrucción. La descripción de esa instrucción es prácticamente idéntica a la instrucción C # throw
(excepto que no restringe el tipo de objeto a System.Exception
):
Descripción:
La throw
instrucción arroja el objeto de excepción (tipo O
) en la pila y vacía la pila. Para obtener detalles sobre el mecanismo de excepción, consulte la Partición I.
[Nota: Aunque la CLI permite que se lance cualquier objeto, la CLS describe una clase de excepción específica que se utilizará para la interoperabilidad de idiomas. nota final]
Excepciones:
System.NullReferenceException
se lanza si obj
es null
.
Exactitud:
El CIL correcto asegura que el objeto sea siempre null
o una referencia de objeto (es decir, de tipo O
).
Creo que estos son suficientes para concluir que las excepciones capturadas nunca lo son null
.