Book Cover

Using the TList Class


There are several important points to remember about the TList class. Most importantly, TList manages its own memory, but does not dereference, allocate, or free memory for the item values. Although TList declares the type of an item as Pointer, you can store anything else that fits into the same amount of memory as a Pointer, such as an Integer, a small set, or an enumerated value. Just remember to use an appropriate type cast, as was shown in Listing 5-2.

If you dynamically allocate memory and store pointers to this memory in a TList, then you must remember to free all the items before freeing the TList object itself. You might find it most convenient to do this by deriving your own class from TList, as shown in Listing 5-3. Be aware that none of the methods of TList are virtual, so you must use your derived class in all type declarations or else Delphi will not call your methods, but those of TList. This inconvenience is addressed later in the chapter, in the section A Better TList Class.

Listing 5-3 TS_ObjectList class derived from TList

type
  TS_ObjectList = class(TList)
  protected
    function GetObject(Index: Integer): TObject;
    procedure SetObject(Index: Integer; Value: TObject);
    procedure SetCount(Value: Integer);
    procedure SetCapacity(Value: Integer);
  public
    destructor Destroy; override;
    procedure Clear;
    procedure Delete(Index: Integer);
    property Objects[Index: Integer]: TObject read GetObject write SetObject;
    property Count write SetCount;
  end;
{ Clear all the objects from the list and destroy the list. }
destructor TS_ObjectList.Destroy;
begin
  Clear;
  inherited Destroy;
end;
{ Return an object from the list. }
function TS_ObjectList.GetObject(Index: Integer): TObject;
begin
  Result := TObject(Items[Index]);
end;
{ Set an object in the list. Free the old object. }
procedure SetObject(Index: Integer; Value: TObject);
begin
  Objects[Index].Free;
  Items[Index] := Pointer(Value);
end;
{ Clear the list by deleting all objects in it. }
procedure TS_ObjectList.Clear;
var
  I: Integer;
begin
  for I := 0 to Count-1 do
    Objects[I].Free;
  inherited Clear;
end;
{ Delete an object from the list, freeing the object }
procedure TS_ObjectList.Delete(Index: Integer);
begin
  Objects[Index].Free;
  inherited Delete(Index);
end;
{ If the list shrinks, free the objects that are implicitly deleted. }
procedure TS_ObjectList.SetCount(Value: Integer);
begin
  while Value < Count then
    Delete(Count-1);
  inherited Count := Value;
end;


Copyright © 1996 Waite Group Press