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?
Packis 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
IsEmptyfunc is not meant for "remove all items from the list where this and that applies".That being said for your task using
Packis not the solution. You will have to use a backwards loop andDelete. When using aTObjectList<T>withOwnsObjects = Trueit 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
.Freethe item inside theIsEmptyfunc you provide when you returnTrue. But imho that code is kinda smelly.