Skip to content

TList. To improve array management

The second:

procedure TForm1.addEmployee(pEmp:pEmployee);
begin
  self.EmployeeList.Add(pEmp);
end;

is all here; an add method is already incorporated in TList: every required operation that Add recalls is entailed under this simple word.
Just an advice, but important: every time you assign a value to a pointer variable, which must be used in code, be sure that a value different from nil has been assigned.
Assignment is usually well done, but about pointers is always better to be sure:

if pTempEmployee <> nil then
begin
  ...
end
else begin
  ...
end;

List's items deletion is equally simple; essentially two situations are possible: deletion of the whole list, deletion of one or more items.

The first is immediate by calling the Destroy method; second one requires to recognize items and to delete them singularly, generally with the automation of a loop scanning.

In this last case a for loop is good, but pay attention to an important fact: if you scan from the start of array (index 0) to the last position and delete every element, first time you get ok, second maybe the same, but at a certain point you'll get an error: the application cannot find the item in a specific index.

procedure TForm1.FormClose(Sender: TObject; var CloseAction: TCloseAction);
var
  i,imax:integer;
begin
  imax:=self.findNumberOfEmployees-1;

  //for i:=0 to imax do begin // error: delete only half items, then index out of range
  for i:=imax downto 0 do begin
    dispose( pEmployee(EmployeeList[i]) ); //delete both TEmployee record and pointer
    EmployeeList.Delete(i);    // delete list's item at index i
  end;

  EmployeeList.Free;  //Destroy the list !!!
end;

The commented loop expression is the incorrect, and error or crash is based upon method Delete, which accepts an integer used as index.
If we scan from the last to the first then every deletion is safe, because Delete doesn't limit itself in deletion but rearrange items by moving them a position to left.
So you can imagine what happens if we adopt the other scanning direction: first item deleted and all moved to a lower position, after second item (the third in original array) is deleted and so on. It happens that after half steps the array is become the half size while the index i goes searching out of range. For example:

  • array of 8 items: after 4 steps, array is of 4 items and the index is equal to 4 (the 5th item, which doesn't exist);
  • array of 7 items: after 4 steps, array is of 3 items and the index is equal to 4 (the 5th item, which doesn't exist).

Every time you use a method, you must know everything it does.
So if you read well about Delete method you'll discover it doesn't deallocate (neutralize) the pointer deleted.
That's why in above code you see this code line: dispose(pEmployee(EmployeeList[i])); .
Finally the object EmployeeList is totally deleted with the Free method: after that every trace vanishes.
Freeing action is not needed when you close the application (here we have only the Form's closing event, but closing the main form is same as closing the application); nevertheless is a good habit to do it, to avoid a supplementary jobs to your operating system.

This is quite all about TList, in the obvious limits of this presentation.
We suggest you to use it whenever you think it could be a good choice for homogeneous data management: it works through pointers (it's indeed a collection of pointers) and makes them available to you with some security mechanisms already included in methods (not all, as you've just seen with Delete).

As always here the zip of the Lazarus project: download it!

What else? oh yes... T in TList, or in TObject and so on, simply stands for Type!