Search code examples
c#exceptionfinally

Get thrown exception in finally block


Is there a way, how to get currently thrown exception (if exists)?

I would like reduce amount of code and apply some reuse for task looks like:

Exception thrownException = null;
try {
    // some code with 3rd party classes, which can throw unexpected exceptions
}
catch( Exception exc ) {
    thrownException = exc;
    LogException( exc );
}
finally {
    if ( null == thrownException ) {
        // some code
    }
    else {
        // some code
    }
}

and replace it with this code:

using( ExceptionHelper.LogException() ) {
    // some code with 3rd party classes, which can throw unexpected exceptions
}
using( new ExceptionHelper { ExceptionAction = ()=> /*some cleaning code*/ } ) {
    // some code with 3rd party classes, which can throw unexpected exceptions
}

public class ExceptiohHelper : IDisposable {
    public static ExceptionHelper LogException() {
        return new ExceptionHelper();
    }

    public Action SuccessfulAction {get; set;}
    public Action ExceptionAction {get; set;}

    public void Dispose() {
        Action action;
        Exception thrownException = TheMethodIDontKnow();
        if ( null != thrownException ) {
            LogException( thrownException );
            action = this.ExceptionAction;
        }
        else {
            action = this.SuccessfulAction;
        }

        if ( null != action ) {
            action();
        }
    }
}

Is this scenario posible?

Thanks


Solution

  • What do you think about the following. Instead of looking at the problem as "How to get the last exception?", what if you change it to, "How do I run some piece of code with some more control?"

    For example: Instead of an ExceptionHelper you could have an ActionRunner.

    public class ActionRunner
    {
        public Action AttemptAction { get; set; }
        public Action SuccessfulAction { get; set; }
        public Action ExceptionAction { get; set; }
    
        public void RunAction()
        {
            try
            {
                AttemptAction();
                SuccessfulAction();
            }
            catch (Exception ex)
            {
                LogException(ex);
                ExceptionAction();
            }
        }
    
        private void LogException(Exception thrownException) { /* log here... */ }
    }
    

    It would at least give you some reuse of the SuccessfulAction and ExceptionAction assuming only the AttemptAction varies between calls.

    var actionRunner = new ActionRunner
    {
        AttemptAction = () =>
        {
            Console.WriteLine("Going to throw...");
            throw new Exception("Just throwing");
        },
        ExceptionAction = () => Console.WriteLine("ExceptionAction"),
        SuccessfulAction = () => Console.WriteLine("SuccessfulAction"),
    };
    actionRunner.RunAction();
    
    actionRunner.AttemptAction = () => Console.WriteLine("Running some other code...");
    actionRunner.RunAction();