Follow-up question to this question: (note that this is not a duplicate, I’m asking for alternatives here).
Is there any way to make the following work:
type
List <T> = record
private
FList : TList <T>;
FGuard : IInterface,
procedure CheckCreated;
public
procedure Add(const Value : T);
end;
procedure List <T>.CheckCreated;
begin
if (FGuard = nil) then
begin
FList := TList <T>.Create;
FGuard := TGuard.Create (FList); // guard calls free on list in destructor
end;
end;
procedure List <T>.Add (const Value : T);
begin
CheckCreated;
FList.Add (Value);
end;
Ideally I want to use it like this:
function ReturnHandles : List <THandle>;
begin
Result.Add (2);
Result.Add (3);
end;
As explained in the answers to the linked question, this does not work (which is really a pitty). It will not create a new list on each call.
Unfortunately this does not work either:
function ReturnHandles : List <THandle>;
begin
Initialize (Result);
Result.Add (2);
Result.Add (3);
end;
It leaks the guard interfaces and all the lists, because Initialize just overwrites the interface reference without decrementing the reference count.
Is there any way to make this work? Or would you suggest making this an interface instead of a record and just live with the construction line?
function ReturnHandles : List <THandle>;
begin
Result := List <T>.Create;
Result.Add (2);
Result.Add (3);
end;
Thanks for your help!
This should work fine if I understand you correctly:
The
Finalizecall will ensure that all managed types are set tonilwhich I believe is your intent.This question is very closely related to your previous question and I think that you could make use of
outparameters to simplify the code. A function result is implicitly avarparameter, but if you used an explicitoutparameter it will initialise the managed types as you desire.Personally, since you are introducing an interface into the mix, I think I would be inclined to go all the way and use interfaces exclusively. Or use standard classes and accept the need for try/finally lifetime management.