The reserved word try enables us to construct two different blocks: the exception handler block and the resource protection block. The exception handler block is created with the reserved word except and the resource protection block is created with the reserved word finally. The syntax of the resource protection block in Delphi is:
try finally end;
In C++, the resource protection block looks like this:
try { } __finally { }
The exception handling and resource protection blocks are used differently and act differently. While the statements in the exception handler execute only if the statements in the try block raise an exception, the statements in the finally block are always executed, even if no exceptions are raised by the statements in the try block. If an exception occurs in the try block, the control is passed to the finally block and cleanup code is executed. If no exceptions occur in the try block, the statements in the finally block are executed after the statements in the try block.
The proper way to use the resource protection block is to allocate or otherwise acquire the resource before the try block. After you have acquired the resource, write statements that use the resource inside the try block. When you're finished with the resource, you have to release it. The statements that release the resource should be placed in the finally block.
{ acquire the resource } try { use the acquired resource } finally { release the resource } end;
The resource protection block is often used to ensure that dynamically created objects are released properly. For instance, you should always protect dynamic modal form creation with the try-finally block (see Listings 13-8A and 13-8B).
Listing 13-8A: Dynamically creating a form with resource protection, Delphi version
procedure TForm1.CreateFormClick(Sender: TObject); var NewForm: TForm; begin NewForm := TForm.Create(Self); try NewForm.ShowModal; finally NewForm.Free; end; end;
Listing 13-8B: Dynamically creating a form with resource protection, C++ version
void __fastcall TForm1::CreateFormClick(TObject *Sender) { TForm* NewForm = new TForm(this); try { NewForm->ShowModal(); } __finally { delete NewForm; } }
Listing 13-9 shows an even shorter way to dynamically create a form protected by the try-finally block.
Listing 13-9: Dynamically creating a form with resource protection, revisited
procedure TForm1.CreateFormShortClick(Sender: TObject); begin with TForm.Create(Self) do try ShowModal; finally Free; end; end;
The other difference between the exception handling and the resource handling blocks is that the resource handling block doesn't handle the exception. Thus, if an exception occurs, it will be passed to the first available exception handler. For instance, if you run the following code, the EDivByZero exception will cause the default exception handler to display the message box informing the user about the exception.
procedure TForm1.CreateFormShortClick(Sender: TObject); begin with TForm.Create(Self) do try { raises EDivByZero because the Tag property = 0 } Caption := IntToStr(Top div Tag); ShowModal; finally Free; end; end;
If you want to handle the EDivByZero exception (or any other exception) inside the resource protection block, you have to write a nested exception handler block. The following listing shows how to write a nested exception handler inside the resource protection block. You can also nest resource protection blocks inside other resource protection blocks or exception handling blocks.
Listing 13-10: Nested blocks
procedure TForm1.CreateFormClick(Sender: TObject); begin with TForm.Create(Self) do try try Caption := IntToStr(Top div Tag); except on EDivByZero do Caption := 'Tag = 0'; end; ShowModal; finally Free; end; end;