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.
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.
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.
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.
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()) };
}
}