Júnior Oliveira

C Sharp; Delphi; ASP .NET; PHP; Javascript;

Garbage Collector no Delphi - Parte II

12 Mar 2011 delphi, generics

Olá pessoal, continuando o post anterior de Garbage Collector, agora vou explorar o uso para objetos que herdam a classe TObject.

Em uma thread na lista de discução lista-delphi o membro Caique vez uma colocação perfeita do Garbage Collector no Delphi e como tinha prometido na thread vou compartilhar com vocês a explicação dele. Segue o link da thread.

O Delphi "não" tem Garbage Collector. Entende-se por Garbage Collector uma forma de destruir qualquer objeto fora de contexto como ocorre em plataformas gerenciadas. O que esta demonstrando no seu exemplo é o uso de interfaces e estas sim por definição destroem o objeto a qual estão associadas quando saem do contexto.

Primeiro desenvolvi uma classe que será responsável por coletar os objetos que não estão mais sendo utilizados.

 1 unit GarbageCollector;
 2 
 3 interface
 4 
 5 uses
 6   SysUtils;
 7 
 8 type
 9   ISafeGuard = type IUnknown;
10 
11 type
12   TSafeGuard = class(TInterfacedObject, ISafeGuard)
13   private
14     { Private declarations }
15     FObj: TObject;
16 
17   public
18     { Public declarations }
19     constructor Create(obj: TObject);
20     destructor Destroy(); override;
21 
22   end;
23 
24 function Guard(out SafeGuard : ISafeGuard) : TObject;
25 
26 implementation
27 
28 { TSafeGuard }
29 
30 constructor TSafeGuard.Create(obj: TObject);
31 begin
32   self.FObj := obj;
33 end;
34 
35 destructor TSafeGuard.Destroy();
36 begin
37   if (Assigned(self.FObj)) then
38   begin
39     try
40       FreeAndNil(self.FObj);
41     except
42       on e : EInvalidPointer do
43         { Objeto ja liberado da memoria. }
44     end;
45   end;
46 
47   inherited Destroy();
48 end;
49 
50 function Guard(out SafeGuard: ISafeGuard): TObject;
51 begin
52   Result := TObject.Create();
53   SafeGuard := TSafeGuard.Create(Result);
54 end;
55 
56 end.

Depois criei um Class Helper para a classe TObject do Delphi com isto garantimos que todos os objetos que herdam a classe TObject serão coletados pelo nosso Garbage Collector. Note que estou utilizando Generics para a nossa função New() já realizar o cast no objeto sem agente precisar se preocupar com isto.

 1 unit HelperObject;
 2 
 3 interface
 4 
 5 uses
 6   SysUtils, Generics.Collections, GarbageCollector;
 7 
 8 type
 9   THelperObject = class helper for TObject
10   public
11     { Public declarations }
12     class function New<T>(out SafeGuard: ISafeGuard): T; static;
13 
14   end;
15 
16 implementation
17 
18 { THelperObject }
19 
20 class function THelperObject.New<T>(out SafeGuard: ISafeGuard): T;
21 begin
22   Result := T(Guard(SafeGuard));
23 end;
24 
25 end.

Agora a forma de utilização.

1 var
2   SafeGuard: ISafeGuard;
3   label1: TLabel;
4 
5 begin
6   label1 := TLabel.New<TLabel>(SafeGuard);
7 end;

Para garantir que a memória está sendo liberada, utilize a mesma propriedade do post anterior Garbage Collector no Delphi - Parte I, neste post está explicado detalhadamento como deve ser utilizada.

1 ReportMemoryLeaksOnShutdown := True;

Este foi mais um exemplo em Delphi XE. Espero que tenham gostado e que seja útil de alguma forma a vocês.