Delphi 2009 引入泛型容器 Generics.Collections 後,提供了成對的容器類別:
TList<T>、TQueue<T>、TStack<T>、TDictionary<TKey,TValue>TObjectList<T>、TObjectQueue<T>、TObjectStack<T>、TObjectDictionary<TKey,TValue>這設計呼應了舊版 Classes.TList 與 Contnrs.TObjectList 的關係:當元素為物件時,「物件擁有版」容器在刪除元素或銷毀容器時,會自動釋放物件實例;基礎版則僅移除參考,不負責釋放記憶體。

uses Generics.Collections;
var
List: TList<TButton>; // 基礎版:不管理物件生命週期
ObjList: TObjectList<TButton>; // 物件擁有版:自動釋放物件
procedure TForm1.FormCreate(Sender: TObject);
begin
List := TList<TButton>.Create;
ObjList := TObjectList<TButton>.Create;
// ... 介面初始化略 ...
end;
procedure TForm1.Button1Click(Sender: TObject); // 加入 TList
var btn: TButton;
begin
btn := TButton.Create(Self);
btn.Caption := 'TList 中的 Button';
btn.Parent := Panel1;
List.Add(btn);
end;
procedure TForm1.Button2Click(Sender: TObject); // 從 TList 移除
begin
List.RemoveAt(0); // 僅移除參考,Button 物件仍存在於 Panel1 上
end;
procedure TForm1.Button3Click(Sender: TObject); // 加入 TObjectList
var btn: TButton;
begin
btn := TButton.Create(Self);
btn.Caption := 'TObjectList 中的 Button';
btn.Parent := Panel2;
ObjList.Add(btn);
end;
procedure TForm1.Button4Click(Sender: TObject); // 從 TObjectList 移除
begin
ObjList.RemoveAt(0); // 自動呼叫 btn.Free,Button 從 Panel2 消失
end;
| 操作 | TList<TButton> | TObjectList<TButton> |
|---|---|---|
Add(btn) | 保存參考 | 保存參考,取得擁有權 |
RemoveAt(0) | 移除參考,物件存活 | 移除參考,自動 Free 物件 |
Clear | 清空列表,物件全殘留 | 清空列表,全數 Free 物件 |
容器 Free | 釋放容器本身,元素物件不受影響 | 釋放容器,連帶釋放所有元素物件 |
TObjectList<T> 繼承自 TList<T>,核心差異在於重寫 Notify 方法:
procedure TObjectList<T>Notify(const Item: T; Action: TCollectionNotification);
begin
inherited;
if Action = cnRemoved then
TObject(Item).Free; // 關鍵:移除時自動釋放
end;
TObjectList.Create(False) 可關閉擁有權,但泛型版 無此選項,行為固定為擁有泛型容器的「雙軌制」設計精準對應記憶體管理需求:TObjectList<T> 系列透過編譯期型別檢查與執行期自動釋放,消除了手動 Free 的遺漏風險,是 Delphi 2009+ 管理物件集合的首選方案。