3

I want to write a method that handle exceptions and that will be called inside a catch block. Depending on the type of the exception passed, the exception is either passed as an inner exception of a new exception or simply re-thrown. How to preserve stack trace in the second case ?

Example :

public void TestMethod()
{
    try
    {
        // can throw an exception specific to the project or a .Net exception 
        SomeWorkMethod() 
    }
    catch(Exception ex)
    {
        HandleException(ex);
    }
}

private void HandleException(Exception ex)
{
    if(ex is SpecificException)
         throw ex; //will not preserve stack trace...
    else
         throw new SpecificException(ex);
}

What I would not like to do is, because the pattern is repeated in many places and there will be no factorization :

try
{
    SomeWorkMethod();
}
catch(Exception ex)
{
    if(ex is SpecificException)
         throw;
    else
         throw new SpecificException(ex);
}
2
  • 3
    Why dont you use something like "if (!HandleException(ex)) throw;". I know it is not exactly what you want, but it is simple and and not a big deal like the second example. Commented Jan 24, 2017 at 13:25
  • 2
    Why don't you have a separate catch for the SpecificException? catch(SpecificException e){throw;} Commented Jan 24, 2017 at 13:29

3 Answers 3

6

You need to use throw without specifying the exception to preserve stack trace. This can only be done inside the catch block. What you can do is return from HandleException without throwing the original exception and then use throw right afterwards:

public void TestMethod()
{
    try
    {
        // can throw an exception specific to the project or a .Net exception 
        SomeWorkMethod() 
    }
    catch(Exception ex)
    {
        HandleException(ex);
        throw;
    }
}

private void HandleException(Exception ex)
{
    if(ex is SpecificException)
         return;
    else
         throw new SpecificException(ex);
}

As long as you only use is to categorize the exception, the preferred way is two catch blocks:

public void TestMethod()
{
    try
    {
        // can throw an exception specific to the project or a .Net exception 
        SomeWorkMethod() 
    }
    catch (SpecificException)
    {
        throw;
    }
    catch(Exception ex)
    {
        throw new SpecificException(ex);
    }
}

With C# 6.0 you can also use when to let the exception fall through:

public void TestMethod()
{
    try
    {
        // can throw an exception specific to the project or a .Net exception 
        SomeWorkMethod() 
    }
    catch(Exception ex) when (!(ex is SpecificException))
    {
        throw new SpecificException(ex);
    }
}
Sign up to request clarification or add additional context in comments.

Comments

3

Actually, there's a really nice way of doing this in .Net4.5 using System.Runtime.ExceptionServices.ExceptionDispatchInfo.Capture:

void Main()
{
    try
    {
        throw new Exception(); //appears to be thrown from here
    }
    catch(Exception ex)
    {
        ThrowEx(ex);
    }

}
public void ThrowEx(Exception ex)
{
    if(someCondition)
    {
        //we're in the scope of a `catch` and the exception
        //is "active", so the exception with original stack-trace
        //can be re-thrown with
        ExceptionDispatchInfo.Capture(ex).Throw();
        //the following line is unreachable, but the compiler doesn't realise
        //so we can "tell" the compiler that this branch ends in an exception
        //and avoid having to return anything in the non-void case
        throw new Exception(); 
    }
}

2 Comments

Thanks spender, you answer very precisely my question. However I had not noticed that there are ways to achieve what I need using many catch blocks (second answer from Sefe).
@SylvainB. Indeed. The accepted answer is definitely a more appropriate fit to your needs. Your question reminded me that I'd seen this a while back, so it seemed worth sharing.
-2

Maybe you can try this.

if(ex.Gettype() == typeof(SpecificException))

2 Comments

This doesn't really address the question as far as I can see. Or at least if it does it could do with some added explanation to say how.
This is wrong in many aspects. Why use reflection? What if ex inherits from SpecificException? Why not use regular language constructs like is (which OP is already doing)?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.