Les autres réponses sont tout à fait correctes, mais cette réponse fournit quelques 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("Votre trace de pile:");
Console.WriteLine(e.StackTrace);
Console.WriteLine();
if (e.InnerException == null) {
Console.WriteLine("Pas d'exception interne.");
} else {
Console.WriteLine("Trace de pile de votre exception interne:");
Console.WriteLine(e.InnerException.StackTrace);
}
}
}
static void ThrowTest() {
decimal a = 1m;
decimal b = 0m;
try {
Mult(a, b); // ligne 34
Div(a, b); // ligne 35
Mult(b, a); // ligne 36
Div(b, a); // ligne 37
} catch (ArithmeticException arithExc) {
Console.WriteLine("Gestion d'une {0}.", arithExc.GetType().Name);
// décommenter L'UNE OU L'AUTRE
//throw arithExc;
// OU
//throw;
// OU
//throw new Exception("Nous avons géré et enveloppé votre 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 ligne throw arithExc;
, votre sortie est:
Gestion d'une DivideByZeroException.
Votre trace de pile:
at Program.ThrowTest() dans c:\somepath\Program.cs:ligne 44
at Program.Main() dans c:\somepath\Program.cs:ligne 9
Pas d'exception interne.
Vous avez sûrement perdu des informations sur l'endroit où cette exception s'est produite. Si au lieu de cela vous utilisez la ligne throw;
, voici ce que vous obtenez:
Gestion d'une DivideByZeroException.
Votre trace de pile:
at System.Decimal.FCallDivide(Decimal& d1, Decimal& d2)
at System.Decimal.Divide(Decimal d1, Decimal d2)
at Program.Div(Decimal x, Decimal y) dans c:\somepath\Program.cs:ligne 58
at Program.ThrowTest() dans c:\somepath\Program.cs:ligne 46
at Program.Main() dans c:\somepath\Program.cs:ligne 9
Pas d'exception interne.
C'est beaucoup mieux, car maintenant vous voyez que c'était la méthode Program.Div
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 dans le bloc try
.
Si vous utilisez la troisième alternative, envelopper dans une exception externe, vous ne perdez aucune information:
Gestion d'une DivideByZeroException.
Votre trace de pile:
at Program.ThrowTest() dans c:\somepath\Program.cs:ligne 48
at Program.Main() dans c:\somepath\Program.cs:ligne 9
Trace de pile de votre exception interne:
at System.Decimal.FCallDivide(Decimal& d1, Decimal& d2)
at System.Decimal.Divide(Decimal d1, Decimal d2)
at Program.Div(Decimal x, Decimal y) dans c:\somepath\Program.cs:ligne 58
at Program.ThrowTest() dans c:\somepath\Program.cs:ligne 35
En particulier, vous pouvez voir que c'est la ligne 35 qui provoque le problème. Cependant, cela oblige les gens à rechercher l'InnerException
, et cela semble quelque peu indirect d'utiliser des exceptions internes dans des cas simples.
Dans cet article de blog, ils conservent le numéro de ligne (ligne du bloc try
) en appelant (via réflexion) la méthode interne InternalPreserveStackTrace()
sur l'objet Exception
. Mais il n'est pas recommandé d'utiliser la réflexion de cette manière (le .NET Framework pourrait modifier ses membres internes un jour sans avertissement).
5 votes
Il y a une différence, elle concerne la manière dont la trace de la pile apparaît dans l'exception, mais je ne me souviens pas laquelle est laquelle pour l'instant, donc je ne vais pas la lister comme réponse.
0 votes
@Joel: Merci. Je suppose que l'utilisation de l'exception HandleError est une mauvaise idée. Je voulais juste refactoriser du code de gestion des erreurs.
1 votes
La troisième façon est d'emballer dans une nouvelle exception et de la relancer timwise.blogspot.co.uk/2014/05/…
0 votes
Possible duplicate de différence entre throw et throw new Exception()