Pattern to avoid nested try catch blocks?

后端 未结 16 510
無奈伤痛
無奈伤痛 2020-12-12 12:53

Consider a situation where I have three (or more) ways of performing a calculation, each of which can fail with an exception. In order to attempt each calculation until we f

相关标签:
16条回答
  • 2020-12-12 13:31

    It sounds like your calculations have more valid information to return than just the calculation itself. Perhaps it would make more sense for them to do their own exception handling and return a "results" class that contains error information, value information, etc. Think like the AsyncResult class does following the async pattern. You can then evaluate the real result of the calculation. You can rationalize this by thinking in terms that if a calculation fails, that's just as informational as if it passes. Therefore, an exception is a piece of information, not an "error."

    internal class SomeCalculationResult 
    { 
         internal double? Result { get; private set; } 
         internal Exception Exception { get; private set; }
    }
    
    ...
    
    SomeCalculationResult calcResult = Calc1();
    if (!calcResult.Result.HasValue) calcResult = Calc2();
    if (!calcResult.Result.HasValue) calcResult = Calc3();
    if (!calcResult.Result.HasValue) throw new NoCalcsWorkedException();
    
    // do work with calcResult.Result.Value
    
    ...
    

    Of course, I'm wondering more about the overall architecture that you're using to get these calculations done.

    0 讨论(0)
  • 2020-12-12 13:32

    What about tracking the actions your doing...

    double val;
    string track = string.Empty;
    
    try 
    { 
      track = "Calc1";
      val = calc1(); 
    
      track = "Calc2";
      val = calc2(); 
    
      track = "Calc3";
      val = calc3(); 
    }
    catch (Exception e3)
    {
       throw new NoCalcsWorkedException( track );
    }
    
    0 讨论(0)
  • 2020-12-12 13:34

    Another version of the try method approach. This one allows typed exceptions, since there is an exception type for each calculation:

        public bool Try<T>(Func<double> func, out double d) where T : Exception
        {
          try
          {
            d = func();
            return true;
          }
          catch (T)
          {
            d = 0;
            return false;
          }
        }
    
        // usage:
        double d;
        if (!Try<Calc1Exception>(() = calc1(), out d) && 
            !Try<Calc2Exception>(() = calc2(), out d) && 
            !Try<Calc3Exception>(() = calc3(), out d))
    
          throw new NoCalcsWorkedException();
        }
    
    0 讨论(0)
  • 2020-12-12 13:38

    Just to offer an "outside the box" alternative, how about a recursive function...

    //Calling Code
    double result = DoCalc();
    
    double DoCalc(int c = 1)
    {
       try{
          switch(c){
             case 1: return Calc1();
             case 2: return Calc2();
             case 3: return Calc3();
             default: return CalcDefault();  //default should not be one of the Calcs - infinite loop
          }
       }
       catch{
          return DoCalc(++c);
       }
    }
    

    NOTE: I am by no means saying that this is the best way to get the job done, just a different way

    0 讨论(0)
提交回复
热议问题