【问题标题】:How can I free a generic TList<T>?如何释放通用 TList<T>?
【发布时间】:2019-11-26 07:11:08
【问题描述】:

如何释放通用 TList&lt;T&gt;

我知道我可以在创建 TObjectListAOwnsObjects = True 时使用它。

我很好奇,当T 是非托管引用(指针或类)时,如何以通用方式重写以下方法,以便释放T

procedure FreeList(const List: TList);
var
  i: Integer;
begin
  if (List = nil) then
    Exit;
  for i := Pred(List.Count) downto 0 do
    if Assigned(List[i]) then
      TObject(List[i]).Free;
  List.Clear;
end;

【问题讨论】:

标签: delphi


【解决方案1】:

您可以将T Generic 参数添加到您的过程中(然后必须将其制成类方法才能使用Generic),并在调用@之前使用RTTI检查T是否是类类型987654323@ 在您的列表元素上。

例如:

type
  ListUtils = class
  public
    class procedure ClearList<T>(const List: TList<T>);
  end;

class procedure ListUtils.ClearList<T>(const List: TList<T>);
type
  PObject = ^TObject;
var
  i: Integer;
  Value: T;
begin
  if (List = nil) then
    Exit;
  if GetTypeKind(T) = tkClass then
  // for older compilers that do not have GetTypeKind():
  // if PTypeInfo(TypeInfo(T))^.Kind = tkClass then
  begin
    for i := Pred(List.Count) downto 0 do
    begin
      Value := List[i];
      PObject(@Value)^.Free;
    end;
  end;
  List.Clear;
end;

或者:

uses
  ..., System.Rtti;

type
  ListUtils = class
  public
    class procedure ClearList<T>(const List: TList<T>);
  end;

class procedure ListUtils.ClearList<T>(const List: TList<T>);
var
  i: Integer;
begin
  if (List = nil) then
    Exit;
  if GetTypeKind(T) = tkClass then
  // for older compilers that do not have GetTypeKind():
  // if PTypeInfo(TypeInfo(T))^.Kind = tkClass then
  begin
    for i := Pred(List.Count) downto 0 do
      TValue.From<T>(List[i]).AsObject.Free;
  end;
  List.Clear;
end;

那么你可以这样使用它:

var
  IntList: TList<Integer>;
  ObjList: TList<TSomeClass>;
begin
  IntList := TList<Integer>.Create;
  ...
  // does not call TObject.Free on list elements
  ListUtils.ClearList<Integer>(IntList);
  IntList.Free;

  ObjList := TList<TSomeClass>.Create;
  ...
  // calls TObject.Free on list elements
  ListUtils.ClearList<TSomeClass>(ObjList);
  ObjList.Free;
end;

【讨论】:

  • 谢谢@Remy:如上所述,我的问题是由简单的好奇心产生的,你的回答很满意。
  • 在柏林下无法编译:两个错误。第一个是 E2530 Type parameters not allowed on global procedure or funcion FreeList,第二个是 E2003 Udeclared identifier 'T' at the method signature const List: TList
  • @FabioVitale 哦,是的,我一直忘记泛型不适用于独立程序的问题(我真的很讨厌这种限制)。因此,只需将过程设置为 class 方法即可。我更新了我的答案以表明
  • 嗨@Remy,我仍然在 TObject(List[i]).Free 行收到错误 E2089 Invalid Typecast;
  • 非常感谢@Remy:它就像一个魅力,现在我对整个事情有了更好的把握!
【解决方案2】:

使用通用版本,TObjectList&lt;T&gt;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多