Pascal泛型TMyList<T>实现自动释放对象时T与TObject类型不兼容问题问询
Delphi泛型列表TMyList自动释放元素对象的解决方案
报错原因
Delphi对泛型类型做严格的编译期类型校验,当泛型参数T没有显式声明为class约束时,编译器不允许直接将T类型变量强制转换为TObject,即使你已经通过GetTypeKind在运行时判断了类型是类类型,编译阶段依然会抛出类型不兼容错误。
可行实现方案
方案1:通过无类型指针中转绕过类型检查(无需额外引用单元,性能最优)
通过指针操作绕过编译期类型检查,运行时已通过类型判断保证安全,且泛型的T类型固定,可将类型判断提到循环外减少重复开销:
procedure TMyList<T>.Clear; var Index1: Integer; LObj: TObject; begin if FOwnsObjects and (GetTypeKind(T) = tkClass) then begin Index1 := 0; while Index1 < FCount do begin LObj := TObject(Pointer(@FList^[Index1])^); if LObj <> nil then begin LObj.Free; Pointer(@FList^[Index1])^ := nil; end; Inc(Index1); end; end; {more code..} end;
方案2:使用TValue处理(更规范,兼容性好)
借助RTTI单元的TValue做类型转换,代码可读性更高,不需要手动处理指针:
uses System.Rtti; procedure TMyList<T>.Clear; var Index1: Integer; LVal: TValue; begin if FOwnsObjects and (GetTypeKind(T) = tkClass) then begin for Index1 := 0 to FCount - 1 do begin LVal := TValue.From<T>(FList^[Index1]); if not LVal.IsEmpty and LVal.AsObject <> nil then begin LVal.AsObject.Free; FList^[Index1] := Default(T); end; end; end; {more code..} end;
额外优化建议
如果你的列表仅需要存储类类型对象,可以直接给泛型类加class约束,加完约束后你原来的代码可以直接编译通过,不需要任何中转处理:
type TMyList<T: class> = class // 类实现逻辑 end;
内容的提问来源于stack exchange,提问作者Adem
相关产品推荐
相关产品推荐

