如何释放通用 TList<T>?

Fab*_*ale 3 delphi

我如何释放泛型TList<T>

我知道我可以在创建它时使用TObjectListwith 。AOwnsObjects = 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;
Run Code Online (Sandbox Code Playgroud)

Rem*_*eau 5

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

例如:

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;
Run Code Online (Sandbox Code Playgroud)

或者:

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;
Run Code Online (Sandbox Code Playgroud)

然后你可以像这样使用它:

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;
Run Code Online (Sandbox Code Playgroud)