我如何释放泛型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)
您可以将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)
| 归档时间: |
|
| 查看次数: |
896 次 |
| 最近记录: |