2568 votes

Attraper plusieurs Exceptions à la fois?

Il est fortement déconseillé de simplement attraper System.Exception, au lieu de seulement les "connus" des Exceptions doivent être pris.

Maintenant, ce qui conduit parfois à unneccessary répétitif code, par exemple:

try
{
    WebId = new Guid(queryString["web"]);
}
catch (FormatException)
{
    WebId = Guid.Empty;
}
catch (OverflowException)
{
    WebId = Guid.Empty;
}

Je me demande: Est-il possible d'attraper les Exceptions et appeler l' WebId = Guid.Empty appel une fois?

Edit: l'exemple donné est plutôt simple, puisqu'il est seulement un Guid. Mais imaginez Code lorsque vous modifiez un objet à plusieurs reprises, et si l'une des manipulations échec de la manière prévue, vous voulez "reset" de l'objet. Cependant, si il ya une Exception inattendue, j'ai encore envie de jeter supérieur.

Réponse: Merci à tous! Pour une raison quelconque, j'ai eu mon état d'esprit sur un switch-case déclaration qui ne prend pas en charge la commutation sur GetType(). Maintenant, il y avait deux réponses, l'une utilisant "typeof" et une aide "is". J'ai d'abord pensé typeof() serait ma Fonction car j'ai pensé: "Hé, je ne veux attraper FormatException parce que c'est la seule chose que j'attends". Mais ce n'est pas la façon dont catch() travaux: catch attire aussi tous les dérivés des exceptions. Après réflexion, c'est vraiment évident: dans le cas Contraire, catch(Exception ex) ne fonctionnerait pas! Donc la bonne réponse est "is". Yay, a appris deux choses avec une seule question \o/

2449voto

Joseph Daigle Points 16429

Catch System.Exception et de basculer sur les types

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

    throw;
}

872voto

Craig Points 848

Je sais que je suis un peu en retard à la fête ici, mais sainte fumée...

Coupe droite à la chasse, ce genre de doublons d'une précédente réponse, mais si vous voulez vraiment effectuer une action commune pour plusieurs types d'exceptions et de garder le tout propre et bien rangé dans le champ d'application de la méthode, pourquoi ne pas simplement utiliser une lambda/fermeture/fonction inline faire quelque chose comme ce qui suit? Je veux dire, les chances sont très bonnes que vous finirez par réaliser que vous voulez juste faire que de la fermeture d'une méthode distincte que vous pouvez utiliser partout. Mais alors, il sera très facile de le faire sans changer le reste du code structurellement. Droit?

private void TestMethod ()
{
    Action<Exception> errorHandler = ( ex ) => {
        // write to a log, whatever...
    };

    try
        {
        // try some stuff
        }
    catch ( FormatException  ex ) { errorHandler ( ex ); }
    catch ( OverflowException ex ) { errorHandler ( ex ); }
    catch ( ArgumentNullException ex ) { errorHandler ( ex ); }
}

Je ne peux pas m'empêcher de me demander (avertissement: un peu d'ironie/sarcasme à l'avance) pourquoi aller à tous ces efforts tout simplement de remplacer le suivant:

try
    {
    // try some stuff
    }
catch( FormatException ex ){}
catch( OverflowException ex ){}
catch( ArgumentNullException ex ){}

...avec un peu fou variation de cette odeur de code, je veux dire exemple, seulement pour faire semblant que vous êtes en train d'enregistrer quelques séquences de touches.

// sorta sucks, let's be honest...
try
    {
    // try some stuff
    }
catch( Exception ex )
    {
    if (
        ex is FormatException
        || ex is OverflowException
        || ex is ArgumentNullException
        )
        {
        // write to a log, whatever...
        return;
        }
    throw;
    }

Parce qu'il n'est certainement pas automatiquement plus lisible.

Accordé, j'ai laissé les trois identiques cas d' /* write to a log, whatever... */ return; sur le premier exemple.

Mais c'est une sorte de mon point de vue. Y'all ont entendu parler de fonctions/méthodes, droit? Sérieusement. Écrire une commune ErrorHandler de la fonction et, comme, à l'appel de chaque bloc catch.

Si vous me demandez, le deuxième exemple (avec l' if et is mots-clés) est à la fois nettement moins lisible, et en même temps significativement plus d'erreurs au cours de la phase d'entretien de votre projet.

La phase de maintenance, pour toute personne qui pourrait être relativement nouveau à la programmation, va se composent de 98,7% ou plus de l'ensemble de la durée de vie de votre projet, et le pauvre con de l'entretien est presque certainement va être quelqu'un d'autre que vous. Et il ya une très bonne chance ils vont passer 50% de leur temps sur le travail en maudissant votre nom.

Et bien sûr, FxCop aboie à vous et donc vous devez également ajouter un attribut à votre code qui a précisément zip à voir avec le programme en cours d'exécution, et n'est là que pour dire FxCop à ignorer un problème que dans 99,9% des cas, il est tout à fait correcte dans le marquage. Et, désolé, j'ai peut-être tort, mais n'est-ce pas "ignorer" attribut finissent effectivement compilé dans votre application?

Serait de mettre l'ensemble de l' if test sur une ligne de la rendre plus lisible? Je ne le pense pas. Je veux dire, j'ai eu un autre programmeur soutiennent avec véhémence une fois il y a longtemps que, mettre plus de code sur une seule ligne rendrait "courir plus vite". Mais bien sûr, il était complétement noix. En essayant de lui expliquer (avec un visage impassible, qui a été difficile) comment l'interpréteur ou compilateur de casser cette longue ligne à part dans discrètes d'une instruction par ligne, états-essentiellement identique au résultat, s'il était allé de l'avant et vient de faire le code lisible au lieu d'essayer de hors-intelligente-le compilateur--a eu aucun effet sur lui que ce soit. Mais je m'égare.

Comment beaucoup moins lisibles cela est-il lorsque vous ajoutez plus de trois types d'exception, un mois ou deux à partir de maintenant? (Réponse: il reçoit beaucoup moins lisible).

L'un des points les plus importants, vraiment, c'est que la plupart du point de mise en forme le texte du code source que nous sommes tous à la recherche à tous les jours est de le faire vraiment, vraiment évident pour les autres êtres humains, ce qui se passe réellement lorsque le code s'exécute. Parce que le compilateur transforme le code source en quelque chose de totalement différent et je ne pouvais pas moins de soins sur votre code de style de mise en forme. Donc tous sur une ligne totalement merdique, trop.

Juste pour dire...

// super sucks...
catch( Exception ex )
    {
    if ( ex is FormatException || ex is OverflowException || ex is ArgumentNullException )
        {
        // write to a log, whatever...
        return;
        }
    throw;
    }

503voto

Joe Points 758

Comme d'autres l'ont souligné, vous pouvez avoir un if déclaration à l'intérieur de votre bloc catch pour déterminer ce qui se passe. Annoncé lors de la compilation de 2014, la prochaine version sera support de Filtres d'Exception, donc la suivante:

try { … }
catch (MyException e) if (myfilter(e))
{
    …
}

Vous pouvez télécharger l'aperçu de Roslyn maintenant vérifier cela.

206voto

Greg Beech Points 55270

En C#, malheureusement, que vous auriez besoin d'un filtre d'exception pour le faire et C# ne pas exposer la fonctionnalité de MSIL. VB.NET n'ont cette capacité si, par exemple,

Catch ex As Exception When TypeOf ex Is FormatException OrElse TypeOf ex Is OverflowException

Ce que vous pourriez faire est d'utiliser une fonction anonyme pour encapsuler votre code d'erreur, puis l'appeler dans les blocs catch:

Action onError = () => WebId = Guid.Empty;
try
{
    // something
}
catch (FormatException)
{
    onError();
}
catch (OverflowException)
{
    onError();
}

149voto

Athari Points 7821

Par souci d'exhaustivité, depuis .NET 4.0 le code réécrit comme suit:

Guid.TryParse(queryString["web"], out WebId);

TryParse jamais lève des exceptions et retourne false si le format est incorrect, réglage WebId d' Guid.Empty.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X