locked
C# Feature Request: Finally block that doesn't mask the original exception. RRS feed

  • Question

  • I write a lot of code like this when I want the original exception to escalate and not my cleanup code in the finally block.

    try
    {
        //may crash
    }
    finally
    {
        try
        {
            //cleanup
        }
        catch (Exception ex)
        {       
           //log but ignore so the first exception escalates
        }
    }

    I know it's too late to change the behavior of the finally block due to existing logical usage but it would be nice to have another block that just escalates the original exception and not the cleanup code exception. Plus, it gives me the shivers to write a catch on Exception. I don't know what to call this new block though, 'finally-try' maybe.

    Monday, February 14, 2011 2:20 PM

All replies

  • Hi Tomasz,

    Your description is unclear and puzzles me. Can you please give me a detailed one?

    Best Regards,


    Cookie Luo[MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Wednesday, February 16, 2011 6:34 AM
  • Sorry for the confusion and the long wait. Let me try again. Basically when the finally block throws an exception I would like a nice way to code up a way to let the outstanding exception propagate instead of the finally block exception. Hopefully this code will help explain it:

     

            private static void Main()
            {
                DoStuff(); //results in DatabaseException but I want the RootException
                DoStuff2(); //results in RootException but somewhat nasty code

                //proposed
                DoStuff3(); //would result in RootException
            }

            private static void DoStuff()
            {
                try
                {
                    throw new RootException();
                }
                finally
                {
                    LogProgress();
                }
            }

            private static void LogProgress()
            {
                throw new DatabaseException();
            }

            private static void DoStuff2()
            {
                Exception temp = null;
                try
                {
                    throw new RootException();
                }
                catch (Exception ex)
                {
                    temp = ex;

                    throw;
                }
                finally
                {
                    try
                    {
                        LogProgress();
                    }
                    catch (Exception ex)
                    {
                        if (temp == null)

                        {
                             throw; //only throw this exception when there is no exception outstanding

                        }
                    }
                }
            }

            private static void DoStuff3()
            {
                try
                {
                    throw new RootException();
                }
                finally-try
                {
                    LogProgress();
                }
            }

    Monday, March 28, 2011 6:13 PM
  • I think you are wanting this. To make it easier you can wrap it around an IDisposable so you can execute logic conditionally while you can enclose the code in a using block which makes it easier to read.

    An application of this logic is employed by the Tracing library which the ApiChange tool uses.

     

    Yours,

       Alois Kraus

     

    Tuesday, March 29, 2011 4:42 PM

  • Hi Thomas,

    How about the below code. It does exactly what you want.

        class MainClass
        {
            public static void Main()
            {
                try
                {
                    SomeFunction();
                }
                catch(Exception exce)
                {
                    Console.WriteLine(exce.Message);
                }

                Console.ReadLine();
            } 

            public static void SomeFunction()
            {
                bool ExceptionOccurerd = true;
                try
                {
                    throw new RootException("Root Exception");
                    ExceptionOccurerd = false;
                }
                finally
                {
                    if (!ExceptionOccurerd)
                    {
                        try
                        {
                            throw new DatabaseException("Database Exception");
                        }
                        catch (Exception exce)
                        {
                            throw;
                        }
                    }
                }
            }
        }

    Any thoughts?


    Please mark this post as answer if it solved your problem. Happy Programming !!!
    • Proposed as answer by Vidya Bhatt Saturday, April 30, 2011 5:39 AM
    Tuesday, March 29, 2011 5:40 PM
  • Tomasz,

    I understand the dilema, but sometimes we expect the language and the framework to do too much for us.  Because there are no restrictions on what can happen in a finally block, there are just too many things to account for.

    re: //log but ignore so the first exception escalates

    Love this comment.  I don't have enough fingers to count the number of times I've corrected the following pattern in coworker's and even third-party code.

    void LogException(Exception x)
    {
      try
      {
        // some log mechanism like:
        File.AppendAllText("debug.log", x.ToString());
      }
      catch(Exception y)
      {
        // can you say stack overflow?
        LogException(y);
      }
    }
    

     Really the best answer is to do your best to create cleanup routines that do not raise exceptions.  True that it's not always possible, but always a worthy effort.

     

     


    This signature unintentionally left blank.
    Wednesday, April 20, 2011 10:22 AM