Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C#: Exception handling in recursive call

I have a recursive method call. When any exception is thrown, I would like to see, where in the recursive call stack it happened. I have a field which holds a "path" which represents the recursion stack.

Now I would like to add the path information to any exception that could possibly be thrown in the recursive call.

void Recursive(int x)
{
  // maintain the recursion path information
  path.Push(x);

  try
  {
    // do some stuff and recursively call the method
    Recursive(x + 6);
  }
  catch(Exception ex)
  {
    if (ex is RecursionException)
    {
      // The exception is already wrapped
      throw;
    }
    // wrap the exception, this should be done only once.
    // save the path and original exception to the wrapper.
    throw new RecursionException(path.ToString(), ex);
  }
  finally
  {
    // maintain the recursion path information
    path.Pop()
  }
}

It just looks too complicated. There is not only one method. There are probably twenty or even more places where I had to write this code.

Is there any simpler way to implement this?


Edit: To point this out: I would like to have a much simpler situation where there is not such an overhead to recursively call the method, because I have many such recursive calls, there is not only one method, there are a couple of methods recursively calling each other, which is complex enough.

So I would like to avoid the whole try - catch block, but I can't see any solution for this.

It is not a big problem for Exceptions thrown in my own code, because it could include the path from the beginning. But it is a problem with every other exception.


Edit: The Exceptions need to be wrapped in any other code, not only when calling the recursive method:

  try
  {
    int a = 78 / x; // DivisionByZeroExeption        

    Recursive(x + 6);

    this.NullReference.Add(x); // NullReferenceException
  }

So wrapping only the call to Recusive does not work.

there are many such methods, having different signatures, doing different things, the only common thing is the exception handling.

like image 979
Stefan Steinegger Avatar asked Oct 19 '09 12:10

Stefan Steinegger


2 Answers

Just simplifying (slightly) the exception handling:

void Recursive(int x)
{
    // maintain the recursion path information
    path.Push(x);

    try
    {
        // do some stuff and recursively call the method
        Recursive(x + 6);
    }
    catch( RecursionException )
    {
        throw;
    }
    catch( Exception )
    {
        throw new RecursionException(path.ToString(), ex);
    }
    finally
    {
        // maintain the recursion path information
        path.Pop()
    }
}

You get callstack info in with Exception if that's of any use to you, beyond that you could write this as a snippet then just insert that where you need to for re-usability.

There's also the following possibility, which would be slow but should work:

void DoStuff()
{
    this.Recursive(1, this.RecursiveFunction1);
    this.Recursive(2, this.RecursiveFunction2);
}

bool RecursiveFunction1(int x)
{
    bool continueRecursing = false;

    // do some stuff
    return continueRecursing;
}

bool RecursiveFunction2(int y)
{
    bool continueRecursing = false;

    // do some other stuff here
    return continueRecursing;
}

private void Recursive(int x, Func<int, bool> actionPerformer)
{
    // maintain the recursion path information
    path.Push(x);

    try
    {
        // recursively call the method
        if( actionPerformer(x) )
        {
            Recursive(x + 6, actionPerformer);
        }
    }
    catch( RecursionException )
    {
        throw;
    }
    catch( Exception ex )
    {
        throw new RecursionException(path.ToString(), ex);
    }
    finally
    {
        // maintain the recursion path information
        path.Pop();
    }
}
like image 184
Dave D Avatar answered Oct 29 '22 21:10

Dave D


What about yanking the catch handler out of the recursive function and just writing the recursion without less of the handling?

void StartRecursion(int x)
{
    try
    {
        path.Clear();
        Recursive(x);
    }
    catch (Exception ex)
    {
        throw new RecursionException(path.ToString(), ex);
    }
}

void Recursive(int x)
{
    path.Push(x);
    Recursive(x + 6);
    path.Pop();
}

void Main()
{
    StartRecursion(100);
}
like image 29
John Fisher Avatar answered Oct 29 '22 21:10

John Fisher