Les autres réponses sont entièrement correctes, mais cette réponse fournit des détails supplémentaires, je pense.
Considérez cet exemple:
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 vous décommentez la throw arithExc;
ligne, votre sortie est:
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.
Vous avez certainement perdu des informations sur le lieu de cette exception. Si vous utilisez plutôt la throw;
ligne, voici ce que vous obtenez:
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.
C'est beaucoup mieux, car maintenant vous voyez que c'est la Program.Div
méthode qui vous a posé problème. Mais il est toujours difficile de voir si ce problème vient de la ligne 35 ou de la ligne 37 du try
bloc.
Si vous utilisez la troisième alternative, encapsulant dans une exception externe, vous ne perdez aucune information:
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 particulier, vous pouvez voir que c'est la ligne 35 qui pose problème. Cependant, cela nécessite que les gens recherchent le InnerException
, et il semble quelque peu indirect d'utiliser des exceptions internes dans des cas simples.
Dans ce billet de blog, ils conservent le numéro de ligne (ligne du bloc try) en appelant (par réflexion) la internal
méthode intance InternalPreserveStackTrace()
sur l' Exception
objet. Mais ce n'est pas agréable d'utiliser une réflexion comme celle-ci (le .NET Framework pourrait changer leurs internal
membres un jour sans avertissement).