Try Block Statements

A 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: finally and except. Any individual try block can specify either or both of these sections, and in either order.

Finally Sections

A 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. DoSomethingMore and AndDoYetMore of course are not.

Except Sections

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.

Inside the except block, one or more on/do clauses can be provided to filter for specific exceptions. Note that the except block can either contain regular code statements or on/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.

Multiple on/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;

Here, both FileNotFoundException and HttpException types are caught, with a different handler being run depending on the error code in the HttpException. Any other exception will continue uncaught.

Re-raising Exceptions

Inside an 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.

Combining finally and except

Both finally and 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;

See Also