Las otras respuestas son completamente correctas, pero esta respuesta proporciona algunos detalles adicionales, creo.
Considere este ejemplo:
using System;
static class Program {
static void Main() {
try {
ThrowTest();
} catch (Exception e) {
Console.WriteLine("Your stack trace:");
Console.WriteLine(e.StackTrace);
Console.WriteLine();
if (e.InnerException == null) {
Console.WriteLine("No inner exception.");
} else {
Console.WriteLine("Stack trace of your inner exception:");
Console.WriteLine(e.InnerException.StackTrace);
}
}
}
static void ThrowTest() {
decimal a = 1m;
decimal b = 0m;
try {
Mult(a, b); // line 34
Div(a, b); // line 35
Mult(b, a); // line 36
Div(b, a); // line 37
} catch (ArithmeticException arithExc) {
Console.WriteLine("Handling a {0}.", arithExc.GetType().Name);
// uncomment EITHER
//throw arithExc;
// OR
//throw;
// OR
//throw new Exception("We handled and wrapped your exception", arithExc);
}
}
static void Mult(decimal x, decimal y) {
decimal.Multiply(x, y);
}
static void Div(decimal x, decimal y) {
decimal.Divide(x, y);
}
}
Si descomenta la throw arithExc;
línea, su salida es:
Handling a DivideByZeroException.
Your stack trace:
at Program.ThrowTest() in c:\somepath\Program.cs:line 44
at Program.Main() in c:\somepath\Program.cs:line 9
No inner exception.
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:
Handling a DivideByZeroException.
Your stack trace:
at System.Decimal.FCallDivide(Decimal& d1, Decimal& d2)
at System.Decimal.Divide(Decimal d1, Decimal d2)
at Program.Div(Decimal x, Decimal y) in c:\somepath\Program.cs:line 58
at Program.ThrowTest() in c:\somepath\Program.cs:line 46
at Program.Main() in c:\somepath\Program.cs:line 9
No inner exception.
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 del try
bloque.
Si usa la tercera alternativa, envolviendo una excepción externa, no pierde información:
Handling a DivideByZeroException.
Your stack trace:
at Program.ThrowTest() in c:\somepath\Program.cs:line 48
at Program.Main() in c:\somepath\Program.cs:line 9
Stack trace of your inner exception:
at System.Decimal.FCallDivide(Decimal& d1, Decimal& d2)
at System.Decimal.Divide(Decimal d1, Decimal d2)
at Program.Div(Decimal x, Decimal y) in c:\somepath\Program.cs:line 58
at Program.ThrowTest() in c:\somepath\Program.cs:line 35
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 intance InternalPreserveStackTrace()
en el Exception
objeto. Pero no es bueno usar una reflexión como esa (.NET Framework podría cambiar a sus internal
miembros algún día sin previo aviso).