C # Est-ce que j’ai besoin de TRY / CATCH pour lancer?

Si tout ce que je veux faire, c’est élever l’exception d’un niveau lorsqu’elle se produit?

private void TryCatch() { try { foo(); } catch (Exception ex) { throw; } } private void NoTryCatch() { foo(); } 

Ces deux méthodes ne sont-elles pas les mêmes?

Si une exception se produit dans TryCatch, elle sera levée d’un niveau et si une exception se produit dans NoTryCatch, l’exception sera également levée d’un niveau.

Cette question a été soulevée après avoir utilisé ReSharper et constaté qu’il suggérait de supprimer le bloc try / catch car il était redondant.

Oui, ces méthodes sont à peu près identiques (*). La seule différence est qu’il est facile de placer un point d’arrêt dans le premier. J’y allais toujours avec la seconde sauf si j’avais vraiment besoin de faire une pause là-bas et seulement là-bas (au contraire d’emblée, des exceptions de ce type ont été lancées, ce qui serait facile). Même si j’avais déjà utilisé le premier, je le remettrais au deuxième formulaire avant de valider le code.

(*) Il peut y avoir des différences dans la façon dont l’ECM les gère. Le premier aboutira avec plus de IL, ce qui affectera les opportunités d’inline, etc.

EDIT: Je ne peux pas résister à un peu de micro-benchmarking. Il semble que try / catch / throw a des effets plus néfastes sur les performances que simplement désactiver l’inline:

 using System; using System.Diagnostics; using System.Runtime.ComstackrServices; public class Test { const int Iterations = 1000000000; static void Main() { Stopwatch sw; sw = Stopwatch.StartNew(); for (int i=0; i < Iterations; i++) { SimpleMethod(); } sw.Stop(); Console.WriteLine("Simple method: {0}", sw.ElapsedMilliseconds); sw = Stopwatch.StartNew(); for (int i=0; i < Iterations; i++) { NoInlining(); } sw.Stop(); Console.WriteLine("No inlining: {0}", sw.ElapsedMilliseconds); sw = Stopwatch.StartNew(); for (int i=0; i < Iterations; i++) { TryCatchThrow(); } sw.Stop(); Console.WriteLine("try/catch/throw: {0}", sw.ElapsedMilliseconds); } static void SimpleMethod() { Foo(); } [MethodImpl(MethodImplOptions.NoInlining)] static void NoInlining() { } static void TryCatchThrow() { try { Foo(); } catch (Exception) { throw; } } static void Foo() {} } 

Comstackr avec /o+ /debug-

Résultats (trois essais):

Méthode simple: 504, 495, 489
Aucune ligne: 2977, 3060, 3019
try / catch / throw: 5274, 4543, 5145

Non, vous n’avez pas besoin d’essayer d’attraper. La seule raison pour laquelle vous voudriez utiliser la première fonction est si vous souhaitez effectuer une journalisation ou libérer des ressources avant de traiter la fonction ultérieurement.

Ces deux méthodes sont essentiellement les mêmes. Dans ce cas, ReSharper avait raison avec sa suggestion.

Quelque chose auquel j’ai pensé, mais comme je n’étais pas sûr à 100%, je suis allé vérifier. J’avais raison parfois.

Apparemment, si vous relancez l’exception, comme le fait votre code, vous risquez de changer la trace de stack. Tout d’abord, si vous deviez écrire throw ex; cela réinitialiserait la trace de stack. Deuxièmement, même en écrivant le throw; il peut également y avoir des cas où des informations sont manquantes. Voir cet article et les commentaires de certains utilisateurs .

Bien sûr, la plupart de ces problèmes sont liés au traçage de stack et aux numéros de ligne, qui sont importants, mais j’ai pensé que cela affecterait également les performances, non seulement à cause de l’insertion (ou de son absence), mais aussi attraper exception et jeter des frais généraux, mais je n’ai rien trouvé de concret à ce sujet.

Ils ne sont vraiment pas les mêmes. Throw le seul ou throw ex bazar throw ex avec les informations de trace de la stack et peut rendre le débogage plus difficile.

La meilleure raison d’attraper une exception est d’append un contexte à la trace de la stack, comme ceci:

 try { Foo(); } catch (Exception e) { throw new BetterException("I did something slightly silly", e); } 

ReSharper est correct. Sauf si vous avez réellement l’intention d’intercepter et de faire quelque chose à propos d’une exception, il est inutile d’inclure un bloc try..catch.

Oui, le bloc catch catch est redondant. La stack sera simplement déroulée jusqu’à ce qu’un test / capture soit trouvé pour gérer l’exception.

Si vous ne faites que renvoyer l’exception, vous n’avez pas besoin du bloc try / catch. En règle générale, vous ne devez intercepter les exceptions que lorsque vous pouvez les gérer. Sinon, laissez-les se propager vers le haut.