112 votes

Modèle à éviter imbriquée try catch blocs ?

Considérons une situation où j'ai eu trois (ou plus) des moyens d'exécution d'un calcul, dont chacun peut échouer avec une exception. Pour tenter de chaque calcul jusqu'à ce que nous en trouver un qui réussit, j'ai été faire les opérations suivantes:

double val;

try { val = calc1(); }
catch (Calc1Exception e1)
{ 
    try { val = calc2(); }
    catch (Calc2Exception e2)
    {
        try { val = calc3(); }
        catch (Calc3Exception e3)
        {
            throw new NoCalcsWorkedException();
        }
    }
}

Est-il un modèle qui parvient dans une jolie manière? Bien sûr, je pourrais envelopper chaque calcul dans une méthode d'assistance qui retourne null en cas d'échec, puis il suffit d'utiliser l' ?? de l'opérateur, mais est-il un moyen de le faire de façon plus générale (c'est à dire sans avoir à écrire une méthode d'assistance pour chaque méthode que je veux utiliser)? J'ai pensé à écrire une méthode statique à l'aide de médicaments génériques qui enveloppe toute méthode dans un try/catch et retourne null en cas d'échec, mais je ne suis pas sûr de comment je pourrais aller à ce sujet. Des idées?

126voto

Ani Points 59747

Dans la mesure du possible, n’utilisez pas exceptions pour le flux de contrôle ou de circonstances rien d’exceptionnel.

Mais pour répondre à votre question directement (en supposant que tous les types exception est les mêmes) :

38voto

musefan Points 23208

Juste pour offrir une alternative « sortir des sentiers battus », que diriez-vous d’une fonction récursive...

NOTE : je ne dis pas que c’est la meilleure façon de faire le travail, juste une autre façon

37voto

Wyzard Points 16284

Vous pourriez s’aplatissent la nidification en le plaçant dans une méthode comme ceci :

Mais je soupçonne que le véritable problème de conception est l’existence de trois méthodes différentes qui font essentiellement la même chose (du point de vue de l’appelant) mais qui lèvent des exceptions différentes, sans rapport.

C’est en supposant que les trois exceptions sont indépendants. Si elles ont toutes une classe de base commune, il serait préférable d’utiliser une boucle avec un bloc catch unique, comme suggéré d’Ani.

20voto

Mohamed Abed Points 2951

Essayez de ne pas la logique de contrôle basée sur les exceptions; note également que les exceptions doivent être jetés dans des cas exceptionnels. Les calculs dans la plupart des cas ne devraient pas jeter des exceptions, sauf si ils ont accès à des ressources externes ou analyser des chaînes ou quelque chose. De toute façon, dans le pire des cas, suivez les TryMethod style (comme TryParse()) pour encapsuler la logique d'exception et faire de votre flux de contrôle facile à entretenir et à nettoyer:

bool TryCalculate(out double paramOut)
{
  try
  {
    // do some calculations
    return true;
  }
  catch(Exception e)
  { 
     // do some handling
    return false;
  }

}

double calcOutput;
if(!TryCalc1(inputParam, out calcOutput))
  TryCalc2(inputParam, out calcOutput);

Une autre variation en utilisant l'essai de modèle et la combinaison de la liste des méthodes à la place de if imbriquées:

internal delegate bool TryCalculation(out double output);

TryCalculation[] tryCalcs = { calc1, calc2, calc3 };

double calcOutput;
foreach (var tryCalc in tryCalcs.Where(tryCalc => tryCalc(out calcOutput)))
  break;

et si le foreach est un peu compliqué, vous pouvez le faire plaine:

        foreach (var tryCalc in tryCalcs)
        {
            if (tryCalc(out calcOutput)) break;
        }

9voto

Lirik Points 17868

Créer une liste de délégués à vos fonctions de calcul et puis avoir un certain temps en boucle pour parcourir les :

Cela devrait vous donner une idée générale de comment le faire (c.-à-d. il n’est pas une solution exacte).

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