Le altre risposte sono del tutto corrette, ma questa risposta fornisce qualche dettaglio in più, credo.
Considera questo esempio:
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 si decommenta la throw arithExc;
riga, l'output è:
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, hai perso informazioni su dove si è verificata tale eccezione. Se invece usi la throw;
linea, ecco cosa ottieni:
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.
Questo è molto meglio, perché ora vedi che è stato il Program.Div
metodo a causarti problemi. Ma è ancora difficile vedere se questo problema proviene dalla linea 35 o dalla linea 37 nel try
blocco.
Se usi la terza alternativa, racchiudendo un'eccezione esterna, non perdi alcuna informazione:
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
In particolare puoi vedere che è la linea 35 che porta al problema. Tuttavia, ciò richiede che le persone effettuino ricerche in InnerException
, e sembra in qualche modo indiretto usare eccezioni interne in casi semplici.
In questo post conservano il numero di riga (riga del blocco try) chiamando (attraverso la riflessione) il internal
metodo intance InternalPreserveStackTrace()
sul Exception
oggetto. Ma non è bello usare la riflessione in questo modo (.NET Framework potrebbe cambiare i loro internal
membri un giorno senza preavviso).