Try Block Statements
try statement surrounds a protected block that receives special treatment when an Exception occurs during its execution, whether in the
try block itself, or any other code that is called from within the block.
Two types of handler sections can be provided at the end of the
try block, to determine what happens when an exception occurs:
except. Any individual
try block can specify either or both of these sections, and in either order.
finally section can provide code that will always execute, whether an exception occurs or not. Recall that normally an exception terminates all execution flow on the current thread, terminating the current method, and its callers, until the the point where the exception is handled. Code inside the
finally section is an exception (pardon the pun) to that.
Finally sections are useful for cleanup code that must be ensured to run even in case of exceptions – for example to close unmanaged resources such as an open file:
try DoSoemthing; MaybeThrowsAnException; DoSomethingMore; finally Cleanup; end; AndDoYetMore;
In this example,
Cleanup would always be called, even if
MaybeThrowsAnException indeed does throw an exception.
AndDoYetMore of course are not.
By contrast, an
except section will only run if an exception occurs and it will handle (or "catch") the exception, so that execution flow will continue normally as if nothing happened:
try DoSoemthing; MaybeThrowsAnException; DoSomethingMore; except writeLn("An error occurred"); end; AndDoYetMore;
In this example, the
writeLn would only be called if
MaybeThrowsAnException (or any other code in the
try block) does throw an exception. Since the exception is then considered handled,
AndDoYetMore would be called as well.
except block, one or more
do clauses can be provided to filter for specific exceptions. Note that the
except block can either contain regular code statements or
do clauses, but not mix both:
try DoSoemthing; MaybeThrowsAnException; DoSomethingMore; except on E: FileNotFoundException do writeLn("Can't load that file. moving on without"); end; AndDoYetMore;
In this case, the
except block only handles the exception if it is of the right type. Any other exception will continue to bubble up the call stack.
do clauses are allowed, and an optional
where condition can be used to filter exceptions on criteria other than their type. Note that only the first clause that matches a given exception is executed, and the exception is only considered handled if it did match one of the clauses:
try DoSoemthing; MaybeThrowsAnException; DoSomethingMore; except on E: FileNotFoundException do writeLn("Can't load that file. moving on without"); on E: HttpException where E.Code = 404 do writeLn("Can't load that webpage. moving on without"); on E: HttpException do writeLn("Different web error"); end; AndDoYetMore;
HttpException types are caught, with a different handler being run depending on the error code in the
HttpException. Any other exception will continue uncaught.
except section, code may decide to not handle the exception after all, and to re-raise it. This can be done by using the
raise Statement or a
raise Expression on its own, without specifying a new exception expression:
except on E: FileNotFoundException do if FileName = "ReallyImortant.txt" then raise; writeLn("Can't load that file, but it seems unimportant..."); end;
Note that using
raise without an expression will let the current exception continue untouched, preserving all its information, including the original call stack. Using
raise E or even
raise new Exception(...) would instead raise the (or a new) exception fresh, losing the history.
except sections can be combined within a single
trt block. In case of an exception, they will be run in the order they have been specified:
try DoSoemthing; MaybeThrowsAnException; DoSomethingMore; finally Cleanup; except writeLn("An error occurred, but we cleaned up fine."); end; AndDoYetMore;