tags:

views:

267

answers:

6

Does anybody know if it's possible to write the code in the catch block below as a single statement? I haven't been able to come up with a way, and was just curious if there was one.

IMPORTANT: the stack trace must be preserved.

    catch (Exception e)
    {
        if (e is MyCustomException)
        {
            // throw original exception
            throw;
        }

        // create custom exception
        MyCustomException e2 =
            new MyCustomException(
                "An error occurred performing the calculation.", e);
        throw e2;
    }
+2  A: 
catch (Exception e)
{
   if (e is MyCustomException) throw;

   throw new MyCustomException("An error occurred performing the calculation.", e);
}

I think that's about as terse as it gets, I think.

This immediately throws MyCustomException up the stack (which is what you're accomplishing with throw; in your question) while throwing a MyCustomException to wrap other Exception types encountered in execution.

Alternatively, you can just do:

catch (Exception e)
{
   throw new MyCustomException("An error occurred performing the calculation.", e);
}

and in the case where MyCustomException was caught, you'll have a MyCustomException in e.InnerException where is e a MyCustomException at the next level of the stack OR you'll have a System.Exception in the cases that MyCustomException is not what was caught.

antik
Am I wrong or throw new will reset the stack?
Svetlozar Angelov
`throw e;` would reset the stack.
antik
No, if Exception is already MyCustomException, then you will double wrap it, so you end up with MyCustomException with an inner exception of MyCustomException.
dcp
A: 
catch (Exception e)
{
    throw !e is MyCustomException ? throw new MyCustomException("message", e) : e;
}

This will shrink it down but it essentially does the same thing.

Doh... no, this will definitely not work. hmm... you still end up with your code, or an inverted version with an else, but that's redundant.

Bill Forney
No, that will reset the stack trace if e is already MyCustomException.
dcp
+15  A: 

What about:

catch (MyCustomException)
{
   throw;
}
catch (Exception ex)
{
   throw new MyCustomException(ex);
}
winSharp93
Yes, that will work, but it's still 2 statements (just across separate catch blocks).
dcp
Isn't this begging the question?
Dave
However, it looks much nicer than the other ones do. And code length is not the only thing you should pay attention to.
winSharp93
Agreed, but this code has already been mentioned in the comments to the original question. Maybe just a disagreement in how SO is supposed to work, but a response that answers a different question may not be the most helpful. The question is, "Is it possible to write the code in the catch block below as a single statement?" The answer is, "No." </grinch>
Dave
@Dave - I don't know what you mean by "begging the question". The challenge was to write the code in the catch block in a single statement (please refer to the original post)@winSharp93 - Again, I was just trying to see if there was a way to write it as a single statement. Code length isn't the only thing I'm paying attention to, it was just a "is it possible" question.
dcp
@dcp: my "begging the question" comment was to the answer, not your comment. :)
Dave
@Dave - oops, my apologies :)
dcp
>> Agreed, but this code has already been mentioned in the comments to the original questionSorry - I didn't see that.
winSharp93
A: 

I know that this isn't answering your original question, however its worth noting that you should be careful when using throw - although miles better than throw ex, there may still be circumstances where using throw does not preserve the stack trace. See:

http://weblogs.asp.net/fmarguerie/archive/2008/01/02/rethrowing-exceptions-and-preserving-the-full-call-stack-trace.aspx

Kragen
A: 

It is actually possible.

However, the stacktrace will contain additional entries:

public static class ExceptionHelper
{
    public static void Wrap<TException>(Action action, Func<Exception, TException> exceptionCallback)
        where TException : Exception
    {
        try
        {
            action();
        }
        catch (TException)
        {
            throw;
        }
        catch (Exception ex)
        {
            throw exceptionCallback(ex);
        }
    }
}
//Usage:
ExceptionHelper.Wrap(() => this.Foo(), inner => new MyCustomException("Message", inner));
winSharp93
A: 

Would this work?

        catch (Exception e)
        {
            throw e.GetType() == typeof(MyCustomException) ? e : new MyCustomException("An error occurred performing the calculation.", e);
        }
TabbyCool
`throw e` is not equivalent to `throw`
Blorgbeard
Good point! I don't know if this can be done in a single line of code then, although I have no idea why this would be required anyway, unless it was more of an academic question than an actual requirement.
TabbyCool