Reputation: 140
Consider a simple class TMyObject that contains an array[0..9] of string (Description) and some other properties (omitted for this example). At a certain point, I want to remove all "empty" objects (i.e. where all 10 string are empty) from FMyList (TList<TMyObject>). For this purpose I am using the Pack method with the IsEmpty function:
FMyList.Pack(
function(const MyObject1, MyObject2: TMyObject): boolean
var
ii: Integer;
begin
result := true;
for ii := 0 to 9 do
if (MyObject1.Description[ii] <> '') then
begin
result := false;
break;
end;
end);
Initially I (wrongfully) assumed Pack would also free (release) the objects. This is not the case, so the above code causes memory leaks, leaving the removed TMyObjects "dangling".
Unfortunately, the documentation is a bit sparse on Pack. How to correctly use this method and ensure that after a Pack, not only are the objects removed from the TList but also correctly freed?
Upvotes: 1
Views: 543
Reputation: 21713
Pack
is specifically to remove empty items from the list with empty being related to the data type. That is why it does not trigger any OnChange event as it technically does not remove items but just empty slots in the backing array.
The overload with IsEmpty
func is not meant for "remove all items from the list where this and that applies".
That being said for your task using Pack
is not the solution. You will have to use a backwards loop and Delete
. When using a TObjectList<T>
with OwnsObjects = True
it will automatically destroy the object. Otherwise you need to do that yourself.
Edit: Just to mention this for completeness sake - but I advise against doing this: you can still .Free
the item inside the IsEmpty
func you provide when you return True
. But imho that code is kinda smelly.
Upvotes: 4