Est-ce toujours une mauvaise pratique d’attraper System.Exception?

Veuillez considérer le code suivant, qui génère trois exceptions différentes (à savoir, System.Configuration.ConfigurationErrorsException , System.FormatException et System.OverflowException ):

 int SomeInt = Convert.ToInt32(ConfigurationManager.AppSettings["SomeIntValue"]); 

Les exceptions sont différentes et, en pratique, je devrais donc avoir trois blocs catch différents pour gérer chaque exception particulière. Cependant, dans ce cas particulier, toutes les exceptions sont gérées de la même manière: un journal est écrit dans, par exemple, EventViewer, et un message informant d’une erreur de configuration est affiché … Dans cette cause particulière, est-il trop mauvais d’utiliser

 try { int SomeInt = ConfigurationManager.AppSettings["SomeIntValue"]; } catch (Exception ThisException) { /* Log and display error message. */ } 

ou devrais-je plutôt utiliser les trois blocs catch et répéter le code dans chacun d’eux?

Je ne pense pas que ce soit une mauvaise pratique. Si la fonctionnalité souhaitée est “chaque fois que ce code lève une exception, effectuez ces actions”, je pense que la capture de System.Exception est parfaitement appropriée.

Le fait que vous encapsuliez une fonction de structure très spécifique au lieu d’un gros bloc de code personnalisé m’aidera également.

Voir C # Exception Handling Handling Fall Through pour une discussion sur ce problème.

En bref, si vous attrapez l’exception générale, vous devriez vérifier si c’est l’un des types attendus et, si ce n’est pas le cas, le réexaminer.

Mise à jour (et un peu hors de scope)

Aussi, il y a quelques fois je pense qu’il est valide de faire une capture tous. Ceci est très rare, mais parfois dans les services Web ou si vous faites quelque chose sur le fil de fond dans asp.net car excepté, l’application entière redémarrera et les utilisateurs risquent de perdre leur session si vous en avez pris une dépendance.

Il est déconseillé d’attraper System.Exception. . . ou mieux encore, il est déconseillé de gérer System.Exception n’importe où sauf au niveau supérieur de votre application. Ce que vous devriez faire est:

  1. Catch System.Exception
  2. Testez l’exception pour les types que vous prévoyez de gérer à l’identique
  3. Renouveler si ce n’est pas l’un de ceux-là.

Exemple de code:

 catch (Exception ex) { if (ex is FormatException || ex is OverflowException || ex is ConfigurationErrorsException) { CommonHandler(); } else { throw; } } 

Ce n’est pas nécessairement une mauvaise pratique, la mauvaise pratique se produit généralement lorsque vous faites des bêtises dans le bloc. La capture de la classe d’exception de base est une bonne mesure de sécurité en supposant que vous deviez agir lorsque l’erreur se produit. La meilleure solution consiste à intercepter une classe d’exception spécifique lorsque cette classe spécifique vous fournit des informations sur lesquelles vous pouvez agir. La capture de SqlException, par exemple, peut vous aider à examiner certaines propriétés spécifiques à cette classe et vous permet de réagir au problème.

Souvent, les gens attrapent une exception et font quelque chose de stupide comme créer une nouvelle exception ou, pire encore, avaler les détails de l’exception.

Un schéma souvent oublié est que vous pouvez attraper, jouer un revirement.

 catch(Exception ex) { //do something throw; } 

préservant ainsi les détails de l’exception.

Dans ce cas particulier, il est tout à fait possible d’utiliser différents blocs catch, car différentes actions peuvent être entresockets en fonction de l’exception que vous obtenez.

Pour les deux premiers, vous pouvez définir une valeur raisonnable par défaut afin de ne pas gêner inutilement l’utilisateur, puis espérer que le problème se corrige lui-même lorsque vous enregistrez votre fichier. Pour la dernière exception, vous pouvez demander à l’utilisateur s’il souhaite poursuivre le processus de chargement. (dans ce cas, vous définissez une valeur par défaut raisonnable), car le fichier de configuration est évidemment corrompu.

En général, la pensée est la suivante: Dois-je prendre des mesures différentes en ce qui concerne les différents types d’exceptions levées? Plus souvent qu’autrement, la réponse est non, aussi une catch(Exception ex){ /* log... */ } vierge catch(Exception ex){ /* log... */ } (ou même aucune catch si l’exception est toujours fatale) suffit.

Edit: Blanc comme dans un chèque en blanc, pas un bloc vide 🙂

Ce qui est vraiment nécessaire, mais la hiérarchie des exceptions .net ne le fournit pas, est un moyen propre de distinguer les exceptions, ce qui signifie “L’opération demandée n’a pas eu lieu, mais l’état du système est bon, sauf dans la mesure impliquée par l’opération ayant eu lieu “de ceux qui veulent dire” le processeur est en feu, et même essayer de sauvegarder le travail de l’utilisateur actuel ne ferait probablement pas empirer les choses. ” Il existe de nombreux contextes dans lesquels on devrait s’efforcer de capturer toutes les exceptions du premier type, tout en évitant idéalement celles du second. Bien qu’il y ait quelques gradations au-delà des deux précédentes, généralement, lorsque l’on intercepte des exceptions, on ne se soucie pas vraiment de la distinction entre une exception InvalidArgumentException ou une exception InvalidOperationException; Ce qui importe, c’est de savoir si l’état général du système est valide ou corrompu.

Dans l’état actuel des choses, si l’on appelle par exemple un plug-in d’importation de fichier et qu’il lève une exception, je ne suis pas vraiment sûr de pouvoir le faire, sauf d’essayer d’attraper et de redissortingbuer de très mauvaises exceptions, tout en plaçant une boîte de dialog “Ce fichier n’a pas pu être ouvert”. J’espère que l’état du système à ce stade est essentiellement le même que si l’utilisateur n’avait pas essayé d’ouvrir le fichier, mais sans moyen normalisé d’indiquer la gravité des exceptions, je ne pense pas qu’il y ait moyen de s’en assurer.

Incidemment, si j’avais mes commandes, il y aurait une classe ExceptionBase, à partir de laquelle toutes les exceptions dériveraient; la plupart des exceptions dériveraient d’Exception (qui à son tour dériverait d’ExceptionBase), mais des éléments comme ThreadAbortException, StackOverflowException, OutOfMemoryException, etc. seraient dérivés de CriticalException. De cette façon, on pourrait intercepter la plupart des exceptions «inattendues» sans étouffer accidentellement les très mauvaises.