Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Delphi - Generics free

Having the following generics class

 TTuple<T1, T2> = class
  protected
    fItem1: T1;
    fItem2: T2;
  public
    constructor Create; overload;
    constructor Create(Item1: T1; Item2: T2); overload;
    destructor Destroy; override;

    property Item1: T1 read fItem1 write fItem1;
    property Item2: T2 read fItem2 write fItem2;
  end;

constructor TTuple<T1, T2>.Create;
begin
  inherited;
end;

constructor TTuple<T1, T2>.Create(Item1: T1; Item2: T2);
begin
  fItem1 := Item1;
  fItem2 := Item2;
end;

destructor TTuple<T1, T2>.Destroy;
begin
  inherited;
end;

and used in a manner like:

x := TTuple<TObjectList<TMyObjects>, Integer>.Create;

I need to free fitem1 manually. How can I free the fItem1 inside the destructor?

like image 920
RBA Avatar asked Mar 03 '18 10:03

RBA


1 Answers

In the definition of TTuple there is no restrictions on type of T1,T2. That is why you can't call destructor, because it can be any type, double/integer etc. Direct answer to your question:

  PObject(@fItem1).DisposeOf;

But it will work properly only when T1 is class. Proper solution is to define TTuple with restrictions on type:

TTuple<T1: class; T2> = class

Then you can free it in normal way:

fItem1.Free

To make it in Delphi-like style you can create two generic classes:

TTuple<T1,T2> = class
...
end;

TObjectTuple<T1: class; T2> = class<TTuple<T1,T2>>
  ...
  property OwnsKey: boolean;
end;

destructor TObjectTuple<T1,T2>.destroy;
begin
  if OwnsKey then
    FItem1.DisposeOf;
end;

For example look how it is implemented in

TObjectList<T: class>
like image 78
Andrei Galatyn Avatar answered Sep 18 '22 17:09

Andrei Galatyn