Respuestas:
Las construcciones
try { ... }
catch () { ... } /* You can even omit the () here */
try { ... }
catch (Exception e) { ... }
son similares en que ambos detectarán todas las excepciones lanzadas dentro del try
bloque (y, a menos que simplemente esté usando esto para registrar las excepciones, deben evitarse ). Ahora mira estos:
try { ... }
catch ()
{
/* ... */
throw;
}
try { ... }
catch (Exception e)
{
/* ... */
throw;
}
try { ... }
catch (Exception e)
{
/* ... */
throw e;
}
El primer y segundo bloque try-catch son EXACTAMENTE lo mismo, simplemente vuelven a lanzar la excepción actual, y esa excepción mantendrá su "fuente" y el seguimiento de la pila.
El tercer bloque try-catch es diferente. Cuando lanza la excepción, cambiará la fuente y el seguimiento de la pila, de modo que parecerá que la excepción ha sido lanzada desde este método, desde esa misma línea throw e
en el método que contiene ese bloque try-catch.
¿Cual deberías usar? Realmente depende de cada caso.
Digamos que tiene una Person
clase con un .Save()
método que la conservará en una base de datos. Digamos que su aplicación ejecuta el Person.Save()
método en alguna parte. Si su DB se niega a salvar a la Persona, .Save()
lanzará una excepción. ¿Deberías usar throw
o throw e
en este caso? Bueno, eso depende.
Lo que prefiero es hacer:
try {
/* ... */
person.Save();
}
catch(DBException e) {
throw new InvalidPersonException(
"The person has an invalid state and could not be saved!",
e);
}
Esto debería colocar DBException como la "Excepción interna" de la excepción más nueva que se lanza. Entonces, cuando inspeccione esta InvalidPersonException, el seguimiento de la pila contendrá información del método Save (que podría ser suficiente para que usted resuelva el problema), pero aún tiene acceso a la excepción original si la necesita.
Como comentario final, cuando espere una excepción, realmente debería detectar esa excepción específica, y no una general Exception
, es decir, si espera una InvalidPersonException, debería preferir:
try { ... }
catch (InvalidPersonException e) { ... }
a
try { ... }
catch (Exception e) { ... }
¡Buena suerte!
El primero conserva el seguimiento de la pila mientras que el segundo lo restablece. Esto significa que si usa el segundo enfoque, el seguimiento de la pila de la excepción siempre comenzará a partir de este método y perderá el seguimiento de la excepción original, lo que podría ser desastroso para alguien que lea los registros de excepciones, ya que nunca descubrirá la causa original de la excepción. .
El segundo enfoque puede ser útil cuando desea agregar información adicional al seguimiento de la pila, pero se usa así:
try
{
// do something
}
catch (Exception ex)
{
throw new Exception("Additional information...", ex);
}
Hay un blog posterior discusión de las diferencias.
throw
frente throw e
.
Deberías usar
try { }
catch(Exception e)
{ throw }
si desea hacer algo con la excepción antes de volver a lanzarlo (registro, por ejemplo). El lanzamiento solitario conserva el rastro de la pila.
La diferencia entre una captura sin parámetros y una catch(Exception e)
es que obtiene una referencia a la excepción. Desde la versión 2 del marco, las excepciones no administradas se incluyen en una excepción administrada, por lo que la excepción sin parámetros ya no es útil para nada.
La diferencia entre throw;
y throw e;
es que el primero se usa para volver a generar excepciones y el segundo se usa para lanzar una excepción recién creada. Si usa el segundo para volver a generar una excepción, la tratará como una nueva excepción y reemplazará toda la información de la pila desde donde se lanzó originalmente.
Por lo tanto, no debe utilizar ninguna de las alternativas de la pregunta. No debe usar la captura sin parámetros, y debe usar throw;
para volver a generar una excepción.
Además, en la mayoría de los casos, debe usar una clase de excepción más específica que la clase base para todas las excepciones. Solo debe detectar las excepciones que anticipa.
try {
...
} catch (IOException e) {
...
throw;
}
Si desea agregar información al volver a generar la excepción, cree una nueva excepción con la excepción original como una excepción interna para conservar toda la información:
try {
...
} catch (IOException e) {
...
throw new ApplicationException("Some informative error message", e);
}