Hay algunas publicaciones que preguntan cuál es la diferencia entre esos dos.
(¿Por qué tengo que mencionar esto ...?)
Pero mi pregunta es diferente de una manera que estoy llamando "throw ex" en otro método de manejo de error similar a un dios .
public class Program {
public static void Main(string[] args) {
try {
// something
} catch (Exception ex) {
HandleException(ex);
}
}
private static void HandleException(Exception ex) {
if (ex is ThreadAbortException) {
// ignore then,
return;
}
if (ex is ArgumentOutOfRangeException) {
// Log then,
throw ex;
}
if (ex is InvalidOperationException) {
// Show message then,
throw ex;
}
// and so on.
}
}
Si try & catch
se usaran en Main
, entonces usaría throw;
para volver a lanzar el error. Pero en el código simplificado anterior, todas las excepciones pasanHandleException
¿ throw ex;
Tiene el mismo efecto que llamar throw
cuando se llama dentro HandleException
?
c#
.net
exception
exception-handling
dance2die
fuente
fuente
Respuestas:
Sí, hay una diferencia;
throw ex
restablece el seguimiento de la pila (por lo que sus errores parecen originarseHandleException
)throw
no lo hace: el delincuente original sería preservado.fuente
(Publiqué antes, y @Marc Gravell me ha corregido)
Aquí hay una demostración de la diferencia:
y aquí está la salida:
Puede ver que en la Excepción 1, el seguimiento de la pila vuelve al
DivByZero()
método, mientras que en la Excepción 2 no lo hace.Sin embargo, tenga en cuenta que el número de línea que se muestra en
ThrowException1()
yThrowException2()
es el número de línea de lathrow
declaración, no el número de línea de la llamada aDivByZero()
, lo que probablemente tenga sentido ahora que lo pienso un poco ...Salida en modo de liberación
Excepción 1:
Excepción 2:
¿Mantiene el stackTrace original solo en modo de depuración?
fuente
DevideByZero
, por lo que el seguimiento de la pila ES el mismo. tal vez deberías publicar esto como una pregunta propiaLas otras respuestas son completamente correctas, pero esta respuesta proporciona algunos detalles adicionales, creo.
Considere este ejemplo:
Si descomenta la
throw arithExc;
línea, su salida es:Ciertamente, ha perdido información sobre dónde ocurrió esa excepción. Si, en cambio, usa la
throw;
línea, esto es lo que obtiene:Esto es mucho mejor, porque ahora ves que fue el
Program.Div
método el que te causó problemas. Pero aún es difícil ver si este problema proviene de la línea 35 o la línea 37 deltry
bloque.Si usa la tercera alternativa, envolviendo una excepción externa, no pierde información:
En particular, puede ver que es la línea 35 la que conduce al problema. Sin embargo, esto requiere que las personas busquen en el
InnerException
, y se siente algo indirecto usar excepciones internas en casos simples.En esta publicación de blog conservan el número de línea (línea del bloque try) al llamar (a través de la reflexión) al
internal
método de intanceInternalPreserveStackTrace()
en elException
objeto. Pero no es bueno usar una reflexión como esa (.NET Framework podría cambiar a susinternal
miembros algún día sin previo aviso).fuente
comprendamos la diferencia entre tirar y tirar ex. Escuché que en muchas entrevistas de .net se hace esta pregunta común.
Solo para dar una visión general de estos dos términos, throw y throw ex se usan para comprender dónde se produjo la excepción. Throw ex reescribe el rastro de excepción de la pila independientemente de dónde se haya lanzado realmente.
Vamos a entender con un ejemplo.
Vamos a entender el primer tiro.
La salida de lo anterior está abajo.
muestra la jerarquía completa y el nombre del método donde realmente se ha lanzado la excepción ... es M2 -> M2. junto con números de línea
En segundo lugar .. vamos a entender por tirar ex. Simplemente reemplace throw con throw ex en el bloque catch del método M2. como a continuación.
La salida del código ex de lanzamiento es la siguiente.
Puede ver la diferencia en la salida ... throw ex simplemente ignora toda la jerarquía anterior y restablece el seguimiento de la pila con la línea / método donde se escribe throw ex.
fuente
Cuando lo hace
throw ex
, esa excepción lanzada se convierte en la "original". Por lo tanto, todo el seguimiento de pila anterior no estará allí.Si lo hace
throw
, la excepción solo se reducirá y obtendrá el seguimiento completo de la pila.fuente
No, esto hará que la excepción tenga un seguimiento de pila diferente. Solo usar un
throw
objeto sin excepción en elcatch
controlador dejará el seguimiento de la pila sin cambios.Es posible que desee devolver un valor booleano de HandleException, independientemente de si se volverá a lanzar la excepción o no.
fuente
MSDN significa :
fuente
Mira aquí: http://blog-mstechnology.blogspot.de/2010/06/throw-vs-throw-ex.html
Tirar :
Conserva la información de la pila con excepción
Esto se llama "Rethrow"
Si quieres lanzar una nueva excepción,
Lanzar Ex :
No enviará información de la pila con excepción
Esto se llama "Romper la pila"
Si quieres lanzar una nueva excepción,
fuente
Para darle una perspectiva diferente sobre esto, usar throw es particularmente útil si proporciona una API a un cliente y desea proporcionar información detallada de seguimiento de la pila para su biblioteca interna. Al usar throw aquí, obtendría el seguimiento de la pila en este caso de la biblioteca System.IO.File para File.Delete. Si uso throw ex, esa información no se pasará a mi controlador.
fuente
si se comentan todas las líneas 1, 2 y 3 - Salida - ex interno
si se comentan todas las líneas 2 y 3 - Salida - ex interno System.DevideByZeroException: {"Intentó dividir por cero"} ---------
si se comentan todas las líneas 1 y 2 - Salida - ex sistema interno Excepción: dividido por 0 ----
si se comentan todas las líneas 1 y 3 - Salida - ex interno System.DevideByZeroException: {"Intentó dividir por cero"} ---------
y StackTrace se restablecerá en caso de lanzamiento ex;
fuente