Icon Exception Handling

Exceptions are special classes that represent an error that has been raised by code in the application, or by the execution environment/operating system itself. All exceptions descend from the ancestor Exception class, which itself descends from the TObject class. The declaration for the Exception class is as follows:

Exception = class(TObject)
   public
      property Message: String read;
      property UnitName: String read;
      property StackTrace: String read;
   end;

With client browser applications, all native JavaScript Error exceptions are automatically re-bound as Exception instances at runtime so that consistent exception class type interrogation/testing is possible with code that is shared between client and server applications. For server applications, all native execution environment exceptions are created using the Exception class, so no re-binding is necessary.

Raising Exceptions
You can raise an exception at any time by using the raise statement. The raise statement requires an Exception class (or descendant) instance as its only argument:

raise <Exception Class Instance>;

Once an exception is raised, execution stops immediately and the process of unwinding the call stack and triggering exception handlers begins.

The following example shows how to raise an exception that indicates that a parameter was not assigned a valid positive value:

function AddValues(A,B: Integer): Integer;
begin
   if (A < 0) then
      raise Exception.Create('First parameter '+IntToStr(A)+' cannot be negative');
   if (B < 0) then
      raise Exception.Create('Second parameter '+IntToStr(A)+' cannot be negative');
   Result:=(A+B);
end;

Handling Exceptions
Once an exception has been raised, execution immediately stops and the call stack is unwound, with any exception-handling blocks executed as necessary during this process.

Exceptions can be handled by using a try..except code block. The syntax of a try..except code block is:

try
   <Statements>
except
   <Exception-handling statements>
end;

A try..except code block catches any exceptions that occur with the try and except keywords, preventing them from escaping the current function or procedure and unwinding the call stack.

You can access the current exception from inside the except portion of the try..except code block by using the on statement, which uses the following syntax:

on <ExceptionInstanceVariable>: <ExceptionClass> do
   <Statements>

on <ExceptionClass> do
   <Statements>

There are two different variations of the on statement:
  • The first variation specifies a local variable name followed by a colon and an exception class name. This is the most useful type of on statement because it allows you to capture the existing exception instance in a local variable. This is important when you want to examine the exception properties or log them for later examination. The exception class name is used to filter which exception classes are handled by the on statement.


  • The second variation specifies an exception class name only and, again, the exception class name is used to filter which exception classes are handled by the on statement.
The following is an example of using the on statement to log an error message in the IDE using the LogOutput method:

begin
  try
     // Statements that raise exception
  except
     on E: Exception do
        LogOutput(E.Message);
  end;
end;

Please see the Debugging topic for more information on the LogOutput method.

Re-Raising Exceptions
You can re-raise an existing exception by using the raise statement without any arguments. Having the ability to re-raise exceptions is useful in situations where you want to do something with an exception, such as log its associated properties, before allowing the call stack to proceed unwinding.

Information Re-raising exceptions can only be done from within the except portion of a try..except code block, and an attempt to do so outside of this context will cause a compiler error.

The following example expands upon the above example by also re-raising the exception after logging the error message:

begin
  try
     // Statements that raise exception
  except
     on E: Exception do
        LogOutput(E.Message);
     raise;
  end;
end;

Ensuring Code Execution After Exceptions
It is often necessary to ensure that certain statements execute, regardless of whether an exception is raised or not. This is accomplished by using a try..finally code block. The syntax of a try..finally code block is:

try
   <Statements>
finally
   <Statements>
end;

Any statements specified within the finally portion of the try..finally code block will always be executed, which is useful for situations where class instances, or other types of resources, have been allocated and need to be disposed of.

The following example shows the method of a class that toggles an internal Boolean variable in the class, and must ensure that the variable is toggled again before the method exits:

procedure TMyClass.Execute;
begin
   FExecuting:=True;
   try
      // Executing
   finally
      FExecuting:=False;
   end;
end;

Information A try..finally code block also applies to the exit statement. If an exit statement is specified inside of a try..finally code block, the finally portion of the code block will be executed before the function or procedure actually exits.

Visual Client Application Exceptions
If an exception is not handled at run-time with a try..except code block in a visual application, the exception will result in an message dialog appearing with the error message. If you do not want this to occur, you can define a TApplication OnError event handler for the global Application instance that is automatically created for visual client applications. Returning True from this event handler will indicate that the error was handled and will prevent the application from displaying an error dialog.
Image