Description |
The Try keyword is used to mark the start of a block of statements that have error trapping. If an error occurs, the program is not terminated. Instead, control is passed to either a Finally or Except section.
Try is used in a number of ways.
Version 1
In a Try-Finally construct, the Finally statement is guaranteed to be executed absolutely regardless of what happens in the Try clause. However, the Finally clause does not actually handle any exceptions - the program will terminate if no Except clause is found (see notes below).
Try-Finally is normally used by a routine to allow cleanup processing to take place, such as freeing resources, with the exception being correctly passed to the caller to handle.
Version 2
In this version, only if the Try clause generates an exception will the Except clause be executed. This is used to take alternative action when something unexpected goes wrong. The except clause cannot determine the error type however.
Version 3
This is similar to version 2, but specifies different actions for different exception types, such as EInOutError. An Else clause can be used as a catch all for unexpected exception types. The general exception type Exception can be used to catch all exception types.
By assigning a Name to the exception, the message text of the exception (Name.Message) can be obtained for display or other uses.
When an exception is raised in a version 3 setup, if the exception is not acted upon by On or Else statements, then a check is made to see if we are in a nested Try block. If so, the Except clause of this parent Try is processed. If no On or Else clause is found, the program terminates.
The Else clause is not really necessary - it is better to use On E:Exception Do, the generic exception handling, since it still provides the error message (E.Message).
Important : you can determine the type of error that occured by using the generic exception handling - On E:Exception Do. E is a pointer to the exception object that is created by the exception condition. E.ClassName gives the exception type, such as 'EDivByZero', as shown in the final example code.
The following list of exceptions covers the basic types - there are hundreds of exception classes:
Exception | Base class |
EAbort | Abort without dialog box |
EAbstractError | Abstract method error |
AssertionFailed | Assert call failed |
EBitsError | Boolean array error |
ECommonCalendarError | Calendar calc error |
EDateTimeError | DateTime calc error |
EMonthCalError | Month calc error |
EConversionError | Raised by Convert |
EConvertError | Object convert error |
EDatabaseError | Database error |
EExternal | Hardware/Windows error |
EAccessViolation | Access violation |
EControlC | User abort occured |
EExternalException | Other Internal error |
EIntError | Integer calc error |
EDivByZero | Divide by zero |
EIntOverflow | Integer overflow |
ERangeError | Out of value range |
EMathError | Floating point error |
EInvalidArgument | Bad argument value |
EInvalidOp | Inappropriate operation |
EOverflow | Value too large |
EUnderflow | Value too small |
EZeroDivide | Divide by zero |
EStackOverflow | Severe Delphi problem |
EHeapException | Dynamic memory problem |
EInvalidPointer | Bad memory pointer |
EOutOfMemory | Cannot allocate memory |
EInOutError | IO error |
EInvalidCast | Object casting error |
EInvalidOperation | Bad component op |
EMenuError | Menu item error |
EOSError | Operating system error |
EParserError | Parsing error |
EPrinter | Printer error |
EPropertyError | Class property error |
EPropReadOnly | Invalid property access |
EPropWriteOnly | Invalid property access |
EThread | Thread error |
EVariantError | Variant problem |
|
|
Notes |
There are times when you want a construct like this :
Try
...
Except
...
Finally
...
End;
where exceptions are trapped and acted upon, but in all cases, a set of clean up statements are executed. This can be achieved with nested Try statements :
Try
Try
...
Except
...
End;
Finally
...
End;
|
|
Related commands |
Except |
|
Starts the error trapping clause of a Try statement |
Finally |
|
Starts the unconditional code section of a Try statement |
On |
|
Defines exception handling in a Try Except clause |
Raise |
|
Raise an exception |
|
|
|
Example code : Version 1 : Zero divide with a finally clause |
var
number, zero : Integer;
begin // Try to divide an integer by zero - to raise an exception
number := -1;
Try
zero := 0;
number := 1 div zero;
ShowMessage('number / zero = '+IntToStr(number));
finally
if number = -1 then
begin
ShowMessage('Number was not assigned a value - using default');
number := 0;
end;
end;
end;
|
Show full unit code |
Number was not assigned a value - using default
Then, the program terminates with an EDivByZero error message - the finally clause did not trap the error.
|
|
Example code : Version 2 : Zero divide with a plain Except block |
var
number, zero : Integer;
begin // Try to divide an integer by zero - to raise an exception
Try
zero := 0;
number := 1 div zero;
ShowMessage('number / zero = '+IntToStr(number));
except
ShowMessage('Unknown error encountered');
end;
end;
|
Show full unit code |
Unknown error encountered
|
|
Example code : Version 3 : Divide by zero with an Except On clause |
// Full Unit code. // ----------------------------------------------------------- // You must store this code in a unit called Unit1 with a form // called Form1 that has an OnCreate event called FormCreate. unit Unit1; interface uses SysUtils, Forms, Dialogs; type TForm1 = class(TForm) procedure FormCreate(Sender: TObject); end; var Form1: TForm1; implementation {$R *.dfm} // Include form definitions procedure TForm1.FormCreate(Sender: TObject); var
number, zero : Integer;
begin // Try to divide an integer by zero - to raise an exception
Try
zero := 0;
number := 1 div zero;
ShowMessage('number / zero = '+IntToStr(number));
except
on E : Exception do
ShowMessage(E.ClassName+' error raised, with message : '+E.Message);
end;
end; end.
|
Hide full unit code |
EDivByZero error raised with message : Division by zero
|
|