7

Ok, as far as I understand, try/catch blocks try an operation and catch blocks catch exceptions. The more specific exceptions go up top, the more generic towards the bottom of the series of catch blocks. In the following code, I implement try/catch, everything works fine.

As far as I understand, a finally block always executes. Some people have argued that there is no purpose to finally block, because if there is an exception or there isn't, the code after the last catch block gets executed anyways.

However, the argument against this is that if there is an exception thrown in a catch block, there are no subsequent catch blocks to catch that exception. So by putting resource cleanup code in a finally block, you ensure that resources will be released in the event that an exception is thrown in a catch block.

Which is why the following code puzzles me. I throw an exception in the first catch block and the finally block never executes. Why?

*Please note that there is indeed an exception thrown while creating myStreamReader, as the file is actually called generic.txt and is misspelled with purpose, in order to throw the initial exception.

StreamReader myStreamReader = null;

try
{
   myStreamReader = new StreamReader("c:\\genneric.txt");   
   Console.WriteLine(myStreadReader.ReadToEnd());       
}

catch(FileNotFoundException Error)
{
   Console.WriteLine(Error.Message);
   Console.WriteLine(); 
   throw new Exception();
}

catch(Exception Error)
{
   Console.WriteLine(Error.Message);
   Console.WriteLine();
}

finally
{

  if(myStreamReader != null)
  {
    myStreamReader.Close();
  }

  Console.WriteLine("Closed the StreamReader.");
}

VIDEO:

The issue with this block of code originates in this video, at the 27:20 mark:

https://www.youtube.com/watch?v=WxdSb3ZCWYc&list=PLAC325451207E3105&index=41

The guy directly declares that an Exception that occurs in a catch block will not prevent the finally block from executing. I am seeing that it does.

user3308043
  • 797
  • 2
  • 9
  • 20
  • Don't listen to these people telling you there is no purpose, they very likely are not doing it correctly. It is also usually advised to only consume exceptions you can handle. The finally will also run if an unhandled exception occurs. – Adam Houldsworth Mar 13 '14 at 07:56
  • Well I agree with your first statement. However, the finally block does not seem to be running in this case. – user3308043 Mar 13 '14 at 07:57
  • I never get to see the text "Closed the StreamReader". So it's clear that an Exception is thrown in the first catch block, but the finally block does not execute. – user3308043 Mar 13 '14 at 07:57
  • Check this http://stackoverflow.com/questions/1555567/when-is-finally-run-if-you-throw-an-exception-from-the-catch-block – Prasanth V J Mar 13 '14 at 08:21
  • @PrasanthVJ Great link, but the top selected answer (+22) seems to state that the finally block does indeed run. I'm not finding this to be the case. – user3308043 Mar 13 '14 at 08:24

4 Answers4

9

If that new exception is completely unhandled, the entire process is torn down, and the finally block never gets to run.

If there's some other exception handler at a higher level, or an unhandled exception handler has been installed, the finally block does run.


This sample does show "Closed the StreamReader":

    static void Main()
    {
        try
        {
            StreamReader myStreamReader = null;

            try
            {
                myStreamReader = new StreamReader("c:\\genneric.txt");
                Console.WriteLine(myStreamReader.ReadToEnd());
            }

            catch (FileNotFoundException Error)
            {
                Console.WriteLine(Error.Message);
                Console.WriteLine();
                throw new Exception();
            }

            catch (Exception Error)
            {
                Console.WriteLine(Error.Message);
                Console.WriteLine();
            }

            finally
            {

                if (myStreamReader != null)
                {
                    myStreamReader.Close();
                }

                Console.WriteLine("Closed the StreamReader.");
            }
        }
        catch
        {

        }
        Console.WriteLine("Done");
        Console.ReadLine();
    }

Unhandled exception handlers can be registered in the AppDomain.UnhandledException event.

Damien_The_Unbeliever
  • 234,701
  • 27
  • 340
  • 448
  • Excellent, thank you. Then what's the best method to handle Exception thrown in catch blocks? – user3308043 Mar 13 '14 at 08:06
  • @user3308043 - it very much depends on whether there's anything you can *usefully* do to allow the program to continue. That's very specific to the situation and there's no generic advice to offer. Given that your code sample is just a toy (and a broken one too, given that it has a typo and doesn't compile) it's difficult to offer any specific advice for your situation. If there's nothing you can usefully do to allow the program to continue, *let* the exception tear down the process - at least you won't cause any further damage. – Damien_The_Unbeliever Mar 13 '14 at 08:08
  • 27:20 mark in this video https://www.youtube.com/watch?v=WxdSb3ZCWYc&index=41&list=PLAC325451207E3105 – user3308043 Mar 13 '14 at 08:08
  • ^^ if you check out the link, make sure to view the video in 720P – user3308043 Mar 13 '14 at 08:10
  • @user3308043 - Unfortunately, I'm at work and my employer isn't very progressive, so no video for me. – Damien_The_Unbeliever Mar 13 '14 at 08:11
  • The guy in the video basically states that a finally block will execute if an exception is thrown in a catch block. I've found the reverse to be true. He hasn't been wrong thus far so I'm not certain what's going on. Hence my presence here. – user3308043 Mar 13 '14 at 08:13
  • @Damien_The_Unbeliever what do you mean by an "unhandled exception handler" is installed ? is it outside programs environment ? – Dexters Mar 13 '14 at 08:13
  • And yes, I did use thus and hence in the same paragraph. :P – user3308043 Mar 13 '14 at 08:13
4

Your understanding is not correct. See try-finally.

By using a finally block, you can clean up any resources that are allocated in a try block, and you can run code even if an exception occurs in the try block. Typically, the statements of a finally block run when control leaves a try statement. The transfer of control can occur as a result of normal execution, of execution of a break, continue, goto, or return statement, or of propagation of an exception out of the try statement.

So finally does executed if you return for instance out of a try block, but not if you throw from a catch block.

However, if the exception is unhandled, execution of the finally block is dependent on how the exception unwind operation is triggered. That, in turn, is dependent on how your computer is set up.

Marius Bancila
  • 16,053
  • 9
  • 49
  • 91
  • 1
    It *is* executed if you throw from a `catch` block... as long as the exception is caught elsewhere. But +1 anyway, you quoted the same bit of the spec I was about to. – Rawling Mar 13 '14 at 08:01
  • 27:20 mark in the following video : https://www.youtube.com/watch?v=WxdSb3ZCWYc&index=41&list=PLAC325451207E3105 – user3308043 Mar 13 '14 at 08:17
  • he states that finally blocks are always executed in the event that an exception is thrown in a catch block – user3308043 Mar 13 '14 at 08:18
  • 3
    Well then he states wrong. An exception thrown from a Catch block is unhandled, unless it is thrown from a nested Try block and handled by a nested Catch block, ad infinitum. – John Willemse Mar 13 '14 at 08:23
  • Excellent, thank you. That seems to be the case and I am indeed starting to see that he is wrong. I also don't think I'm misunderstanding him, as he nearly directly states it in the video. – user3308043 Mar 13 '14 at 08:49
1

Assuming the file is not found, it would first catch the FileNotFoundException:

catch(FileNotFoundException error)
{
    Console.WriteLine(error.Message);
    Console.WriteLine(); 
    throw new Exception();
}

This writes a message to the console, and then throws a new Exception. This exception however, is unhandled and will halt execution. If you throw an exception from within a Catch block, it will not be caught by any subsequent blocks.

The solution is to handle the exception appropiately instead of throwing a new one. If the file was not found, then act upon it, e.g. let the user choose another file, create the file, etc.

John Willemse
  • 6,608
  • 7
  • 31
  • 45
  • Don't throw them at all, or create a nested Try..Catch block inside the Catch block. It all depends on what you want your user to experience. Generally, you don't want to impose an exception on them, but solve the exception in your code instead without them ever noticing. – John Willemse Mar 13 '14 at 08:07
  • Yes, of course. However, this seems like it could ultimately become a recursive process of multiple exceptions. Logically, it seems to me as if you have to have a default method for catching exceptions in *catch* blocks. – user3308043 Mar 13 '14 at 08:12
0

use throw instead and try this. When you throw a new exception, the actual exception will be lost. But when you use just throw it will throw the actual exception which is FileNotFoundException.

StreamReader myStreamReader = null;

try
{
   myStreamReader = new StreamReader("c:\\genneric.txt");   
   Console.WriteLine(myStreadReader.ReadToEnd());       
}

catch(FileNotFoundException Error)
{
   Console.WriteLine(Error.Message);
   Console.WriteLine(); 
   throw;
}

catch(Exception Error)
{
   Console.WriteLine(Error.Message);
   Console.WriteLine();
}

finally
{
  Console.WriteLine("Closing the StreamReader.");
  try{
    if(myStreamReader != null)
   {
      myStreamReader.Close();
   }
  } catch(Exception e) {  Console.WriteLine(e.ToString())  };
}


}
Dexters
  • 2,419
  • 6
  • 37
  • 57
  • What's the difference between throw; and throw new Exception()? – user3308043 Mar 13 '14 at 08:01
  • Also, there is no need for a try/catch block in the finally statement, as there is no possibility for an error while doing the null test for myStreamReader, as myStreamReader is set to null before the first try block. If it is never created (an error upon creation), it remains null. – user3308043 Mar 13 '14 at 08:02
  • @user3308043 I agree, I do clean up in finally, i just have a catch with just a logging or sometime even empty so that if i have multiple cleanup activities nothing goes wrong. – Dexters Mar 13 '14 at 08:08
  • Ok, but it's really redundant in this case. There is no way for the null check to go wrong. – user3308043 Mar 13 '14 at 08:15