Pattern to avoid nested try catch blocks?

C#Design PatternsTry CatchMonads

C# Problem Overview


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 find one that succeeds, I have been doing the following:

double val;

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

Is there any accepted pattern which achieves this in a nicer way? Of course I could wrap each calculation in a helper method which returns null on failure, and then just use the ?? operator, but is there a way of doing this more generally (i.e. without having to write a helper method for each method I want to use)? I've thought about writing a static method using generics which wraps any given method in a try/catch and returns null on failure, but I'm not sure how I would go about this. Any ideas?

C# Solutions


Solution 1 - C#

As far as possible, don't use exceptions for control flow or unexceptional circumstances.

But to answer your question directly (assuming all the exception-types are the same):

Func<double>[] calcs = { calc1, calc2, calc3 };

foreach(var calc in calcs)
{
   try { return calc(); }
   catch (CalcException){  }
} 

throw new NoCalcsWorkedException();

Solution 2 - C#

You could flatten out the nesting by putting it into a method like this:

private double calcStuff()
{
  try { return calc1(); }
  catch (Calc1Exception e1)
  {
    // Continue on to the code below
  }

  try { return calc2(); }
  catch (Calc2Exception e1)
  {
    // Continue on to the code below
  }

  try { return calc3(); }
  catch (Calc3Exception e1)
  {
    // Continue on to the code below
  }

  throw new NoCalcsWorkedException();
}

But I suspect the real design problem is the existence of three different methods that do essentially the same thing (from the caller's perspective) but throw different, unrelated exceptions.

This is assuming the three exceptions are unrelated. If they all have a common base class, it'd be better to use a loop with a single catch block, as Ani suggested.

Solution 3 - C#

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

Solution 4 - C#

Try not to control logic based on exceptions; note also that exceptions should be thrown only in exceptional cases. Calculations in most cases should not throw exceptions unless they access external resources or parse strings or something. Anyway in the worst case follow the TryMethod style (like TryParse()) to encapsulate exception logic and make your control flow maintainable and clean:

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);

Another variation utilizing the Try pattern and combining list of methods instead of nested if:

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;

and if the foreach is a little complicated you can make it plain:

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

Solution 5 - C#

Create a list of delegates to your calculation functions and then have a while loop to cycle through them:

List<Func<double>> calcMethods = new List<Func<double>>();

// Note: I haven't done this in a while, so I'm not sure if
// this is the correct syntax for Func delegates, but it should
// give you an idea of how to do this.
calcMethods.Add(new Func<double>(calc1));
calcMethods.Add(new Func<double>(calc2));
calcMethods.Add(new Func<double>(calc3));

double val;
for(CalcMethod calc in calcMethods)
{
    try
    {
        val = calc();
        // If you didn't catch an exception, then break out of the loop
        break;
    }
    catch(GenericCalcException e)
    {
        // Not sure what your exception would be, but catch it and continue
    }
    
}

return val; // are you returning the value?

That should give you a general idea of how to do it (i.e. it's not an exact solution).

Solution 6 - C#

This looks like a job for... MONADS! Specifically, the Maybe monad. Start with the Maybe monad as described here. Then add some extension methods. I wrote these extension methods specifically for the problem as you described it. The nice thing about monads is you can write the exact extension methods needed for your situation.

public static Maybe<T> TryGet<T>(this Maybe<T> m, Func<T> getFunction)
{
    // If m has a value, just return m - we want to return the value
    // of the *first* successful TryGet.
    if (m.HasValue)
    {
        return m;
    }

    try
    {
        var value = getFunction();

        // We were able to successfully get a value. Wrap it in a Maybe
        // so that we can continue to chain.
        return value.ToMaybe();
    }
    catch
    {
        // We were unable to get a value. There's nothing else we can do.
        // Hopefully, another TryGet or ThrowIfNone will handle the None.
        return Maybe<T>.None;
    }
}

public static Maybe<T> ThrowIfNone<T>(
    this Maybe<T> m,
    Func<Exception> throwFunction)
{
    if (!m.HasValue)
    {
        // If m does not have a value by now, give up and throw.
        throw throwFunction();
    }

    // Otherwise, pass it on - someone else should unwrap the Maybe and
    // use its value.
    return m;
}

Use it like so:

[Test]
public void ThrowIfNone_ThrowsTheSpecifiedException_GivenNoSuccessfulTryGet()
{
    Assert.That(() =>
        Maybe<double>.None
            .TryGet(() => { throw new Exception(); })
            .TryGet(() => { throw new Exception(); })
            .TryGet(() => { throw new Exception(); })
            .ThrowIfNone(() => new NoCalcsWorkedException())
            .Value,
        Throws.TypeOf<NoCalcsWorkedException>());
}

[Test]
public void Value_ReturnsTheValueOfTheFirstSuccessfulTryGet()
{
    Assert.That(
        Maybe<double>.None
            .TryGet(() => { throw new Exception(); })
            .TryGet(() => 0)
            .TryGet(() => 1)
            .ThrowIfNone(() => new NoCalcsWorkedException())
            .Value,
        Is.EqualTo(0));
}

If you find yourself doing these sorts of calculations often, the maybe monad should reduce the amount of boilerplate code you have to write while increasing the readability of your code.

Solution 7 - C#

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();
    }

Solution 8 - C#

In Perl you can do foo() or bar(), which will execute bar() if foo() fails. In C# we don't see this "if fail, then" construct, but there's an operator that we can use for this purpose: the null-coalesce operator ??, which continues only if the first part is null.

If you can change the signature of your calculations and if you either wrap their exceptions (as shown in previous posts) or rewrite them to return null instead, your code-chain becomes increasingly brief and still easy to read:

double? val = Calc1() ?? Calc2() ?? Calc3() ?? Calc4();
if(!val.HasValue) 
    throw new NoCalcsWorkedException();

I used the following replacements for your functions, which results in the value 40.40 in val.

static double? Calc1() { return null; /* failed */}
static double? Calc2() { return null; /* failed */}
static double? Calc3() { return null; /* failed */}
static double? Calc4() { return 40.40; /* success! */}

I realize that this solution won't always be applicable, but you posed a very interesting question and I believe, even though the thread is relatively old, that this is a pattern worth considering when you can make the amends.

Solution 9 - C#

Given that the calculation methods have the same parameterless signature, you can register them in a list, and iterate through that list and execute the methods. Probably it would be even better for you to use Func<double> meaning "a function that returns a result of type double".

using System;
using System.Collections.Generic;

namespace ConsoleApplication1
{
  class CalculationException : Exception { }
  class Program
  {
    static double Calc1() { throw new CalculationException(); }
    static double Calc2() { throw new CalculationException(); }
    static double Calc3() { return 42.0; }

    static void Main(string[] args)
    {
      var methods = new List<Func<double>> {
        new Func<double>(Calc1),
        new Func<double>(Calc2),
        new Func<double>(Calc3)
    };

    double? result = null;
    foreach (var method in methods)
    {
      try {
        result = method();
        break;
      }
      catch (CalculationException ex) {
        // handle exception
      }
     }
     Console.WriteLine(result.Value);
   }
}

Solution 10 - C#

You can use a Task/ContinueWith, and check for the exception. Here's a nice extension method to help make it pretty:

    static void Main() {
        var task = Task<double>.Factory.StartNew(Calc1)
            .OrIfException(Calc2)
            .OrIfException(Calc3)
            .OrIfException(Calc4);
        Console.WriteLine(task.Result); // shows "3" (the first one that passed)
    }

    static double Calc1() {
        throw new InvalidOperationException();
    }

    static double Calc2() {
        throw new InvalidOperationException();
    }

    static double Calc3() {
        return 3;
    }

    static double Calc4() {
        return 4;
    }
}

static class A {
    public static Task<T> OrIfException<T>(this Task<T> task, Func<T> nextOption) {
        return task.ContinueWith(t => t.Exception == null ? t.Result : nextOption(), TaskContinuationOptions.ExecuteSynchronously);
    }
}

Solution 11 - C#

If the actual type of the exception thrown doesn't matter, you can just use a typeless catch block:

var setters = new[] { calc1, calc2, calc3 };
bool succeeded = false;
foreach(var s in setters)
{
    try
    {
            val = s();
            succeeded = true;
            break;
    }
    catch { /* continue */ }
}
if (!suceeded) throw new NoCalcsWorkedException();

Solution 12 - C#

using System;

namespace Utility
{
	/// <summary>
	/// A helper class for try-catch-related functionality
	/// </summary>
	public static class TryHelper
	{
		/// <summary>
		/// Runs each function in sequence until one throws no exceptions;
		/// if every provided function fails, the exception thrown by
		/// the final one is left unhandled
		/// </summary>
		public static void TryUntilSuccessful( params Action[] functions )
		{
			Exception exception	= null;

			foreach( Action function in functions )
			{
				try
				{
					function();
					return;
				}
				catch( Exception e )
				{
					exception	= e;
				}
			}
	
			throw exception;
		}
	}
}

And use it like so:

using Utility;

...

TryHelper.TryUntilSuccessful(
	() =>
	{
		/* some code */
	},
	() =>
	{
		/* more code */
	},
	calc1,
	calc2,
	calc3,
	() =>
	{
		throw NotImplementedException();
	},
	...
);

Solution 13 - C#

It seems that the OP's intention was to find a good pattern for solving his issue and resolving the current problem that he was struggling with at that moment.

> OP: "I could wrap each calculation in a helper method which returns null on failure, and then just use the ?? operator, but is there a way of doing this more generally (i.e. without having to write a helper method for each method I want to use)? I've thought about writing a static method using generics which wraps any given method in a try/catch and returns null on failure, but I'm not sure how I would go about this. Any ideas?"

I saw a lot of good patterns that avoid nested try catch blocks, posted in this feed, but didn't find a solution to the problem that is cited above. So, here is the solution:

As OP mentioned above, he wanted to make a wrapper object which returns null on failure. I would call it a pod (Exception-safe pod).

public static void Run()
{
	// The general case
	// var safePod1 = SafePod.CreateForValueTypeResult(() => CalcX(5, "abc", obj));
	// var safePod2 = SafePod.CreateForValueTypeResult(() => CalcY("abc", obj));
	// var safePod3 = SafePod.CreateForValueTypeResult(() => CalcZ());

	// If you have parameterless functions/methods, you could simplify it to:
	var safePod1 = SafePod.CreateForValueTypeResult(Calc1);
	var safePod2 = SafePod.CreateForValueTypeResult(Calc2);
	var safePod3 = SafePod.CreateForValueTypeResult(Calc3);

	var w = safePod1() ??
			safePod2() ??
			safePod3() ??
			throw new NoCalcsWorkedException(); // I've tested it on C# 7.2

	Console.Out.WriteLine($"result = {w}"); // w = 2.000001
}

private static double Calc1() => throw new Exception("Intentionally thrown exception");
private static double Calc2() => 2.000001;
private static double Calc3() => 3.000001;

But what if you'd like to create a safe pod for a Reference Type result returned by CalcN() functions/methods.

public static void Run()
{
	var safePod1 = SafePod.CreateForReferenceTypeResult(Calc1);
	var safePod2 = SafePod.CreateForReferenceTypeResult(Calc2);
	var safePod3 = SafePod.CreateForReferenceTypeResult(Calc3);

	User w = safePod1() ?? safePod2() ?? safePod3();

	if (w == null) throw new NoCalcsWorkedException();

	Console.Out.WriteLine($"The user object is {{{w}}}"); // The user object is {Name: Mike}
}

private static User Calc1() => throw new Exception("Intentionally thrown exception");
private static User Calc2() => new User { Name = "Mike" };
private static User Calc3() => new User { Name = "Alex" };

class User
{
	public string Name { get; set; }
	public override string ToString() => $"{nameof(Name)}: {Name}";
}

So, you might notice that there is no need "to write a helper method for each method you want to use".

The two types of pods (for ValueTypeResults and ReferenceTypeResults) are enough.


Here is the code of SafePod. It isn't a container though. Instead, it creates an exception-safe delegate wrapper for both ValueTypeResults and ReferenceTypeResults.

public static class SafePod
{
    public static Func<TResult?> CreateForValueTypeResult<TResult>(Func<TResult> jobUnit) where TResult : struct
    {
        Func<TResult?> wrapperFunc = () =>
        {
            try { return jobUnit.Invoke(); } catch { return null; }
        };

        return wrapperFunc;
    }

    public static Func<TResult> CreateForReferenceTypeResult<TResult>(Func<TResult> jobUnit) where TResult : class
    {
        Func<TResult> wrapperFunc = () =>
        {
            try { return jobUnit.Invoke(); } catch { return null; }
        };

        return wrapperFunc;
    }
}

That's how you can leverage the null-coalescing operator ?? combined with the power of first-class citizen entities (delegates).

Solution 14 - C#

You are right about wrapping each calculation but you should wrap according to the tell-don't-ask-principle.

double calc3WithConvertedException(){
	try { val = calc3(); }
	catch (Calc3Exception e3)
	{
		throw new NoCalcsWorkedException();
	}
}

double calc2DefaultingToCalc3WithConvertedException(){
	try { val = calc2(); }
	catch (Calc2Exception e2)
	{
		//defaulting to simpler method
		return calc3WithConvertedException();
	}
}


double calc1DefaultingToCalc2(){
	try { val = calc2(); }
	catch (Calc1Exception e1)
	{
		//defaulting to simpler method
		return calc2defaultingToCalc3WithConvertedException();
	}
}

The operations are simple, and can change their behaviour independently. And it doesn't matter why they default. As a prove you could implement calc1DefaultingToCalc2 as:

double calc1DefaultingToCalc2(){
	try { 
		val = calc2(); 
		if(specialValue(val)){
			val = calc2DefaultingToCalc3WithConvertedException()
		}
	}
	catch (Calc1Exception e1)
	{
		//defaulting to simpler method
		return calc2defaultingToCalc3WithConvertedException();
	}
}

Solution 15 - C#

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.

Solution 16 - C#

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 );
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionjjoelsonView Question on Stackoverflow
Solution 1 - C#AniView Answer on Stackoverflow
Solution 2 - C#WyzardView Answer on Stackoverflow
Solution 3 - C#musefanView Answer on Stackoverflow
Solution 4 - C#Mohamed AbedView Answer on Stackoverflow
Solution 5 - C#KirilView Answer on Stackoverflow
Solution 6 - C#fre0nView Answer on Stackoverflow
Solution 7 - C#StefanView Answer on Stackoverflow
Solution 8 - C#AbelView Answer on Stackoverflow
Solution 9 - C#Marcin SeredynskiView Answer on Stackoverflow
Solution 10 - C#Dax FohlView Answer on Stackoverflow
Solution 11 - C#Jacob KrallView Answer on Stackoverflow
Solution 12 - C#Ryan LesterView Answer on Stackoverflow
Solution 13 - C#AlexMelwView Answer on Stackoverflow
Solution 14 - C#raisercostinView Answer on Stackoverflow
Solution 15 - C#EmoireView Answer on Stackoverflow
Solution 16 - C#Orn KristjanssonView Answer on Stackoverflow