Garbage Collector no Delphi - Parte II

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.

TSafeGuard.pas
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
unit GarbageCollector;

interface

uses
SysUtils;

type
ISafeGuard = type IUnknown;

type
TSafeGuard = class(TInterfacedObject, ISafeGuard)
private
{ Private declarations }
FObj: TObject;

public
{ Public declarations }
constructor Create(obj: TObject);
destructor Destroy(); override;

end;

function Guard(out SafeGuard : ISafeGuard) : TObject;

implementation

{ TSafeGuard }

constructor TSafeGuard.Create(obj: TObject);
begin
self.FObj := obj;
end;

destructor TSafeGuard.Destroy();
begin
if (Assigned(self.FObj)) then
begin
try
FreeAndNil(self.FObj);
except
on e : EInvalidPointer do
{ Objeto ja liberado da memoria. }
end;
end;

inherited Destroy();
end;

function Guard(out SafeGuard: ISafeGuard): TObject;
begin
Result := TObject.Create();
SafeGuard := TSafeGuard.Create(Result);
end;

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.

THelperObject.pas
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
unit HelperObject;

interface

uses
SysUtils, Generics.Collections, GarbageCollector;

type
THelperObject = class helper for TObject
public
{ Public declarations }
class function New<T>(out SafeGuard: ISafeGuard): T; static;

end;

implementation

{ THelperObject }

class function THelperObject.New<T>(out SafeGuard: ISafeGuard): T;
begin
Result := T(Guard(SafeGuard));
end;

end.

Agora a forma de utilização.

1
2
3
4
5
6
7
var
SafeGuard: ISafeGuard;
label1: TLabel;

begin
label1 := TLabel.New<TLabel>(SafeGuard);
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.