rethrow for debugging


A question came up on an internal email list. 


 



You will get this error in the following code, as per the rules of C#:


 


try


{


….


}


catch(Exception e)


{


// Handle cleanup.


throw;


}


 


With the exception of disabling this specific warning, is there anyway to have the Exception variable in a catch that is not using it (so that debugging is easier) and not hit this warning?


 


Can the warning be disabled only for catch()? (Yeah, I am guessing it can’t too, worth asking. :))


 


The goal is to make it easy to set a breakpoint here & see the details of the exception, without interfering with the behavior of the program.  ‘throw e’ is different from ‘throw’ here.


 


One proposal was to throw a new exception, with ‘e’ as the inner exception.  The proposal relied too much on strings for my taste, so I put this together:


 



    using System;


    using System.Runtime.Serialization;


 


    [Serializable]


    public class RethrownException : ApplicationException


    {


        public static void Throw(Exception exception)


        {


            throw new RethrownException(exception);


        }


 


        public RethrownException(Exception inner) : base(null, inner) { }


 


        public RethrownException(SerializationInfo info, StreamingContext context) : base(info, context) { }


    }


 


And here’s the usage:


 



            try


            {


                throw new System.Exception(“sdfs”);


            }


            catch (System.Exception ex)


            {


                RethrownException.Throw(ex);


            }


 


 


What do you think?


 


 

Comments (14)

  1. David M. Kean says:

    Doesn’t the debugger in 2003 have a special local value called $exception that contains the thrown exception?

  2. It seems that the recommendation from the CLR team these days is avoid deriving from ApplicationException…

    http://blogs.msdn.com/brada/archive/2004/03/25/96251.aspx

  3. Pavel Lebedinsky says:

    I don’t like the wrap and rethrow idea. You are not adding any useful information to the original exception, just making things unnecessarily complicated.

    The original code should just use try/finally.

  4. Eric Gunnerson says:

    When you rethrow this way, you restart the stack trace and therefore lose the context of the original exception.

  5. matthew says:

    you should just

    try {

    }

    catch {

    throw;

    }

  6. Why get rid of the warning? You have $exception and if you still want the ex variable for debugging, the warning is a friendly reminder to get rid of it later on.

  7. Jeff Clark says:

    If there is important information in that method you may want to tracing it out somehow so you can debug the problem in release builds and on non-dev machines too.

    I keep hearing about $exception….how does that work. How do you access it?

  8. jaybaz [MS] says:

    Josh: The guidelines are a bit mixed up. It depends on where you read.

    I’ll have to research it more. We now generate exception implementations for you, so we better get it right!

  9. jaybaz [MS] says:

    Some more notes for you:

    try/finally doesn’t give me the exception in the debugger.

    My rethrow implementation sucks because it chagnes the exception type – a caller can’t catch properly.

    In VS 2003, the debugger has a pseudo variable called "$exception" that is available when you break on a throw. You’ll see this with an unhandled exception, for example.

    In VS 2005, the debugger also shows $exception in a catch block.

    So, in VS2002 and VS2003, the need is still there, but I think I would follow Omer’s approach if I really needed this.

  10. Panos Theofanopoulos says:

    catch(Exception e){

    Debug.WriteLine( e ); // eliminated in release builds

    throw;

    }

  11. jaybaz [MS] says:

    Another option is:

    catch (Exception e)

    {

    Exception temp = e;

    throw;

    }

  12. I’m lazy, I don’t like setting breakpoints here and there – if there’s an exception, I want to be there automatically. So what we did was creating a base exception in our companies base class library, whe each constructor is doing an Assert. Each caught "System.Exception" is rethrown, packed into our base Exception (we use the FxCop Rules). If there’s an exception, Assert will tell me and bring me to the right spot.

    One big disadvantage is that sometimes there are many many Asserts. Thus, to handle "expected" Asserts, we implemented a configurable exception-suppression-mechanism.

  13. Triton says:

    Of course, the base code pattern you’re using here will be flagged as problematic by FxCop: one should stay away from catch-all (catching System.Exception) error handling.

  14. jaybaz [MS] says:

    Triton is right on that one.