web-dev-qa-db-fra.com

Attraper deux exceptions dans le même bloc catch?

J'ai une méthode qui peut lever deux exceptions différentes, CommuncationException et SystemException. Dans les deux cas, je fais le même bloc de code à trois lignes.

try {
 ...
}

catch (CommunicationException ce) {
   ...
}

catch {SystemExcetion se) {
   ... 
}

Y a-t-il une possibilité de le faire comme ça?

try {
   ...
}

catch (CommunicationException ce, SystemException se) {
   ...
}

Ensuite, je n'aurais pas à écrire autant de code. Je sais que je pourrais extraire la gestion des exceptions vers une méthode privée, mais comme le code ne fait que 3 lignes, la définition de la méthode prendrait plus de code que le corps lui-même.

38

En fait, vous ne pourriez attraper que SystemException et il gérerait également CommunicationException, car CommunicationException est dérivé de SystemException

catch (SystemException se) {
   ... //this handles both exceptions
}
25
archil

Si vous pouvez mettre à jour votre application en C # 6, vous avez de la chance. La nouvelle version C # a implémenté des filtres d'exception . Vous pouvez donc écrire ceci:

catch (Exception ex) when (ex is CommunicationException || ex is SystemException) {
    //handle it
}

Certaines personnes pensent que ce code est le même que

catch (Exception ex) {                
    if (ex is CommunicationException || ex is SystemException) {
        //handle it
    }
    throw;
}

Mais ce n'est pas. En fait, c'est la seule nouvelle fonctionnalité de C # 6 qui n'est pas possible d'émuler dans les versions précédentes. Tout d'abord, une relance signifie plus de frais généraux que de sauter le crochet. Deuxièmement, il n'est pas sémantiquement équivalent. La nouvelle fonctionnalité conserve la pile intacte lorsque vous déboguez votre code. Sans cette fonctionnalité, le vidage sur incident est moins utile, voire inutile.

Voir un discussion à ce sujet sur CodePlex . Et un exemple montrant la différence .

147
Maniero

Malheureusement, il n'y a aucun moyen. La syntaxe que vous avez utilisée n'est pas valide et une chute comme dans une instruction switch n'est pas possible non plus. Je pense que vous devez utiliser la méthode privée.

Une petite solution de rechange hacky serait quelque chose comme ceci:

var exceptionHandler = new Action<Exception>(e => { /* your three lines */ });
try
{
    // code that throws
}
catch(CommuncationException ex)
{
    exceptionHandler(ex);
}
catch(SystemException ex)
{
    exceptionHandler(ex);
}

Vous devez décider par vous-même si cela a un sens.

11
Daniel Hilgarth

Non, vous ne pouvez pas le faire de cette façon. La seule façon que je sache est d'attraper une exception générique, puis de vérifier de quel type il s'agit:

try
{
   ...
}
catch(Exception ex)
{
   if(ex is CommunicationException || ex is SystemException)
   {
      ...
   }
   else
   {
     ... // throw; if you don't want to handle it
   }
}
5
alexn

Qu'en est-il de

try {


...
}

catch (CommunicationException ce) {
   HandleMyError(ce);
}

catch {SystemExcetion se) {
   HandleMyError(se);
}

private void HandleMyError(Exception ex)
{
// handle your error
}
3
Gerrie Schenck

Duplicata possible de

Attraper plusieurs exceptions à la fois?

Je cite la réponse ici:

 catch (Exception ex)            
       {                
           if (ex is FormatException ||
               ex is OverflowException)
           {
               WebId = Guid.Empty;
               return;
           }
           else
           {
               throw;
           }
       }
3
Marshal

Puisque vous faites de même pour les deux types d'exceptions, vous pouvez simplement aller:

try
{
    //do stuff
}
catch(Exception ex)
{
    //normal exception handling here
}

N'attrapez des types d'exception explicites que si vous devez faire quelque chose d'unique pour cela.

1
tobias86