2010-06-08 11 views
116

¿cuál es la diferencia entrediferencia entre tiro y lanzar la nueva Excepción()

try { ... } 
catch{ throw } 

y

try{ ... } 
catch(Exception e) {throw new Exception(e.message) } 

Independientemente de que la segunda muestra un mensaje?

+38

El segundo fragmento es una de las líneas de código más malvadas (pero inofensivas) que he visto en mi vida. – SLaks

+0

http://stackoverflow.com/questions/22623/net-throwing-exceptions-best-practices – dotjoe

Respuesta

188

throw; vuelve a generar la excepción original y conserva su traza de pila original.

throw ex; arroja la excepción original pero restablece el seguimiento de la pila, destruyendo toda la información de seguimiento de la pila hasta su bloque catch.


NUNCA escritura throw ex;


throw new Exception(ex.Message); es aún peor. Crea una nueva instancia de Exception, perdiendo el rastro de pila original de la excepción, así como su tipo. (por ejemplo, IOException).
Además, algunas excepciones contienen información adicional (por ejemplo, ArgumentException.ParamName).
throw new Exception(ex.Message); destruirá esta información también.

En algunos casos, es posible que desee ajustar todas las excepciones en un objeto de excepción personalizado, para que pueda proporcionar información adicional sobre lo que estaba haciendo el código cuando se lanzó la excepción.

Para ello, definir una nueva clase que hereda Exception, add all four exception constructors, y opcionalmente un constructor adicional que toma un InnerException, así como información adicional, y lanzar su nueva clase de excepción, pasar ex como el InnerException parámetro . Pasando el InnerException original, conserva todas las propiedades de la excepción original, incluido el seguimiento de la pila.

+13

"throw new Exception (ex); es incluso peor.": No estoy de acuerdo con esta. En ocasiones, desea cambiar el tipo de excepción y mantener la excepción original como excepción interna es lo mejor que puede hacer. Aunque debería ser 'throw new MyCustomException (myMessage, ex);' por supuesto. –

+8

@ 0xA3: quise decir 'ex.Message', que _es_ peor. – SLaks

+6

Además de implementar los constructores estándar, también se deben hacer excepciones personalizadas '[Serializable()]'. –

4

throw vuelve a lanzar la excepción detectada, conservando el seguimiento de la pila, mientras que throw new Exception pierde algunos de los detalles de la excepción detectada.

Normalmente usaría throw por sí mismo para registrar una excepción sin tener que manejarla completamente en ese punto.

BlackWasp tiene un buen artículo suficientemente titulado Throwing Exceptions in C#.

3

throw es para volver a lanzar una excepción atrapada. Esto puede ser útil si desea hacer algo con la excepción antes de pasarlo por la cadena de llamadas.

El uso de throw sin argumentos conserva la pila de llamadas para la depuración.

3

Lanzar una nueva excepción hace desaparecer la traza de la pila actual.

throw; conservará la traza original de la pila y es casi siempre más útil. La excepción a esa regla es cuando desea ajustar la Excepción en una Excepción personalizada propia. A continuación, debe hacer:

catch(Exception e) 
{ 
    throw new CustomException(customMessage, e); 
} 
0

Si lo desea, puede lanzar una nueva Excepción, con el conjunto original como una excepción interna.

19

La primera conserva el StackTrace el original:

try { ... } 
catch 
{ 
    // Do something. 
    throw; 
} 

El segundo le permite cambiar el tipo de excepción y/o el mensaje y otros datos:

try { ... } catch (Exception e) 
{ 
    throw new BarException("Something broke!"); 
} 

También hay una tercera vía donde se pasa una excepción interna:

try { ... } 
catch (FooException e) { 
    throw new BarException("foo", e); 
} 

Yo recomendaría la utilización de:

  • la primera si desea realizar una limpieza en una situación de error sin destruir información o agregar información sobre el error.
  • el tercero si desea agregar más información sobre el error.
  • el segundo si desea ocultar información (de usuarios que no son de confianza).
0

Su segundo ejemplo restablecerá el seguimiento de la pila de la excepción. El primero conserva con mayor precisión los orígenes de la excepción. También ha desenvuelto el tipo original que es clave para saber qué salió mal ... Si el segundo es necesario para la funcionalidad, p. Ej. Para agregar información extendida o volver a envolver con un tipo especial, como una 'Excepción Handleable' personalizada, ¡solo asegúrese de que la propiedad InnerException esté configurada también!

+0

Wow. Cuando comencé a escribir, todavía no había respuestas y ahora me ' número 6 ... – Reddog

+0

Sí, esta es una de esas preguntas en las que tienes que escribir rápido;;) –

0

La diferencia más importante es que la segunda expresión borra el tipo de excepción. Y tipo de excepción juega un papel vital en la captura de excepciones:

public void MyMethod() 
{ 
    // both can throw IOException 
    try { foo(); } catch { throw; } 
    try { bar(); } catch(E) {throw new Exception(E.message); } 
} 

(...) 

try { 
    MyMethod(); 
} catch (IOException ex) { 
    Console.WriteLine ("Error with I/O"); // [1] 
} catch (Exception ex) { 
    Console.WriteLine ("Other error"); // [2] 
} 

Si foo() tiros IOException, [1] bloque catch capturará la excepción. Pero cuando bar() arroja IOException, se convertirá en Exception llano y no será capturado por [1] bloque de captura.

3

Otro punto que yo no vi a nadie hacer:

Si usted no hace nada en su catch {} bloque, teniendo un try ... catch no tiene sentido. Veo esto todo el tiempo:

try 
{ 
    //Code here 
} 
catch 
{ 
    throw; 
} 

O peor:

try 
{ 
    //Code here 
} 
catch(Exception ex) 
{ 
    throw ex; 
} 

Peor aún:

try 
{ 
    //Code here 
} 
catch(Exception ex) 
{ 
    throw new System.Exception(ex.Message); 
} 
+0

Estoy de acuerdo, a menos que tengas la cláusula finally. –

0

tiro o tirar ex, ambos se utilizan para lanzar o volver a lanzar la excepción, cuando simplemente registre la información del error y no quiera enviar ninguna información a la persona que llama, simplemente registra el error en la captura y se va.Pero en caso de que desee enviar información significativa sobre la excepción a la persona que llama, use throw o throw ex. Ahora la diferencia entre throw y throw ex es que throw conserva el seguimiento de la pila y otra información, pero throw ex crea un nuevo objeto de excepción y, por lo tanto, se pierde la traza original de la pila. Entonces, ¿cuándo deberíamos usar throw and throw e, todavía hay algunas situaciones en las que es posible que desee volver a lanzar una excepción como para restablecer la información de la pila de llamadas. Por ejemplo, si el método está en una biblioteca y desea ocultar los detalles de la biblioteca del código de llamada, no necesariamente quiere que la pila de llamadas incluya información sobre métodos privados dentro de la biblioteca. En ese caso, podría detectar excepciones en los métodos públicos de la biblioteca y luego volver a lanzarlos para que la pila de llamadas comience en esos métodos públicos.

0

Throw; Retome la excepción original y mantenga el tipo de excepción.

Lanzar nueva excepción(); Vuelva a colocar el tipo de excepción original y restablezca el seguimiento de la pila de excepción

Throw ex; Restablezca el seguimiento de la pila de excepciones y restablezca el tipo de excepción

Cuestiones relacionadas