2009-09-22 8 views
8

¿Hay alguna diferencia de comportamiento entre:tiro nueva excepción vs bloque Catch

if (s == null) // s is a string 
{ 
throw new NullReferenceException(); 
} 

Y:

try 
{ 
    Console.Writeline(s); 
} 


catch (NullReferenceException Ex) 
{ // logic in here 
} 

Ambas excepciones tiro de objeto nulo, si s es nulo. El primer ejemplo es más legible ya que muestra exactamente dónde se produce el error (el bit de excepción está justo al lado de la línea que causará la excepción).

He visto este estilo de codificación mucho en varios blogs por diferentes codificadores de todo tipo de niveles de habilidad, pero ¿por qué no llevar a cabo la lógica principal comprobando si s no es nulo y así ahorrar la excepción de alguna vez ser levantado? ¿Hay algún inconveniente en este enfoque?

Gracias

+1

+1 Buena pregunta –

Respuesta

18

No, Console.WriteLine(null) no serán una excepción. Simplemente no imprimirá nada. Suponiendo que haya querido decir algo como:

Console.WriteLine(s.Length); 

, entonces tiene sentido ... y debe usar el primer formulario. Las excepciones deben ocurrir cuando no puede predecirlas con anticipación con su información actual. Si puede resolver fácilmente que algo anda mal, no tiene sentido intentar una operación que probablemente falle. Conduce a un código que es más difícil de entender y funciona peor.

Así NullReferenceException, ArgumentNullException y similares no deben ser capturados a menos que sean debido a una nasty API which sometimes throws exceptions which you can handle, but which shouldn't really be being thrown in the first place. Esta es la razón por la cual en Contratos de Código, el comportamiento predeterminado para un contrato fallido es lanzar una excepción que usted no puede atrapar explícitamente, que no sea atrapando (que generalmente está en algún lugar en la parte superior de la pila).

+0

Gracias. Me refiero a cualquier caso donde se usa la variable (en un método/ctor) pero causa una NullReferenceException o referencia de objeto no configurada en una instancia de un error de objeto. Una cosa que me dijo un amigo que codifica es que se debe usar el primer formulario donde la persona que llama capte la excepción. Entonces, si tengo otro método que llama al primer formulario y tiene un bloque catch para la línea de excepción lanzada. ¿Estarías de acuerdo con esto? – dotnetdev

+0

¿Cuál es, si existe alguna, la relación entre la referencia del objeto no establecida en una instancia de un objeto y NRE? – dotnetdev

+0

¿Cómo sabe si la persona que llama captará la excepción? ¿Y cuál es la diferencia entre lanzar explícitamente una excepción cuando algo irá mal (que es mucho más informativo) y dejar que el marco .NET arroje una excepción NullRef genérica? –

2

Como ya mencionó Jon Skeet, Console.WriteLine (null) no lanzará una excepción.

Además de eso, me gustaría decir que debes 'fallar rápido'. Eso significa que debes poner cláusulas de 'guardia' en tus métodos y verificar los argumentos que se han dado en tus métodos si se pueden considerar válidos. Esto le permite lanzar una excepción y proporcionar un mensaje adicional que será útil al depurar. El mensaje puede dar una indicación clara de lo que estaba mal, y eso es mucho más útil que si se enfrenta a una NullReferenceException que se ha lanzado sin buena información en su propiedad de mensaje.

0

Si está tomando un enfoque de diseño por contrato, un fragmento de código puede especificar que arroja excepciones para especificar su contrato y aplicarlo. La otra mitad es, por supuesto, código de llamada que reconoce el contrato y lo cumple.

En este caso, si conoce un método emitirá una excepción si pasa nulo (es decir, su contrato es que no pasa nulos), entonces debe verificar antes de llamarlo.

Jon Skeet dice que el método no arrojará una excepción de todos modos. Eso puede o no ser cierto, pero el principio de proteger los stands de contrato de método (que creo que fue el punto de su pregunta).

1

Si está escribiendo una biblioteca de clases, puede haber ocasiones en que sepa que si un cierto parámetro contiene un valor nulo, eso puede causar problemas más adelante en la línea.En esos casos, generalmente me parece una buena idea lanzar una excepción (aunque probablemente usaría ArgumentNullException para ese caso) para que el usuario de la biblioteca de clases lo sepa lo antes posible y con la mayor claridad posible.

Las excepciones no siempre son malas.

1

Jon Skeet tiene razón pero, en términos más generales, se trata de una cuestión semántica.

Si la situación tiene algún significado aplicativo (número fuera de límite, fecha de nacimiento en el futuro, etc.) es posible que desee probarlo antes de realizar cualquier operación y lanzar una excepción personalizada (es decir, una con significado para su solicitud).

Si la situación es verdaderamente "excepcional", simplemente escriba el código como si el valor dado fuera el correcto. Mira, si pones la prueba, lo harás cada vez, sabiendo que la máquina virtual lo hará de todos modos en caso de que necesite lanzar una excepción. Desde el punto de vista del rendimiento, si el error tiene una ocurrencia estadísticamente pequeña, no tiene sentido.

Cuestiones relacionadas