As outras respostas estão inteiramente corretas, mas acho que essa resposta fornece detalhes adicionais.
Considere este exemplo:
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);
}
}
Se você descomentar a throw arithExc;
linha, sua saída é:
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.
Certamente, você perdeu informações sobre onde essa exceção ocorreu. Se, em vez disso, você usar a throw;
linha, é isso que você obtém:
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.
Isso é muito melhor, porque agora você vê que foi o Program.Div
método que lhe causou problemas. Mas ainda é difícil ver se esse problema vem da linha 35 ou da linha 37 do try
bloco.
Se você usar a terceira alternativa, agrupando uma exceção externa, você não perde nenhuma informação:
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
Em particular, você pode ver que é a linha 35 que leva ao problema. No entanto, isso requer que as pessoas pesquisem o InnerException
, e parece um pouco indireto usar exceções internas em casos simples.
Em este post eles preservam o número da linha (linha do bloco try) pelo telefone (através da reflexão) o internal
método intance InternalPreserveStackTrace()
sobre o Exception
objeto. Mas não é legal usar reflexões como essa (o .NET Framework pode alterar seus internal
membros algum dia sem aviso prévio).