Delphi - 泛型免费版

8
拥有以下泛型类:
 TTuple<T1, T2> = class
  protected
    fItem1: T1;
    fItem2: T2;
  public
    constructor Create; overload;
    constructor Create(Item1: T1; Item2: T2); overload;
    destructor Destroy; override;

    property Item1: T1 read fItem1 write fItem1;
    property Item2: T2 read fItem2 write fItem2;
  end;

constructor TTuple<T1, T2>.Create;
begin
  inherited;
end;

constructor TTuple<T1, T2>.Create(Item1: T1; Item2: T2);
begin
  fItem1 := Item1;
  fItem2 := Item2;
end;

destructor TTuple<T1, T2>.Destroy;
begin
  inherited;
end;

并且以以下方式使用:

x := TTuple<TObjectList<TMyObjects>, Integer>.Create;

我需要手动释放fitem1。如何在析构函数中释放fItem1?


2
只需写 T1: class 而不是 T1,你就掌握了这个技巧。这样,您将拥有一个“不太通用”的通用类型,因为 T1 只能是类类型;由于编译器知道这一事实,您将能够调用 Free。 - Alberto Miola
1
您可以通过查看 System.Generics.Collections 的源代码来学习 Delphi 中使用泛型的许多技巧。TObjectList<T>TObjectDictionary<TKey, TValue> 将向您展示 RTL 如何使用 @AndreiGalatyn 在 此回答 中概述的技术。 - JRL
2
这个类提供了什么?它似乎只是增加了一层复杂度,而我无法看出任何好处。或者这只是一个示例? - David Heffernan
1个回答

9
在TTuple的定义中,对T1、T2的类型没有任何限制。这就是为什么你不能调用析构函数的原因,因为它可以是任何类型,比如double/integer等。直接回答你的问题:
  PObject(@fItem1).DisposeOf;

但是它只有在T1为类时才能正常工作。正确的解决方案是在类型上对TTuple进行限制:

TTuple<T1: class; T2> = class

然后您可以正常释放它:
fItem1.Free

为了以类似Delphi的风格实现,您可以创建两个通用类:
```

要以 Delphi 风格实现,您可以创建两个通用类:

```
TTuple<T1,T2> = class
...
end;

TObjectTuple<T1: class; T2> = class<TTuple<T1,T2>>
  ...
  property OwnsKey: boolean;
end;

destructor TObjectTuple<T1,T2>.destroy;
begin
  if OwnsKey then
    FItem1.DisposeOf;
end;

例如,看看它在实现中是如何运用的。
TObjectList<T: class>

1
这个安全吗?if PTypeInfo(TypeInfo(T1)).Kind = tkClass then PObject(@FItem1).DisposeOf; - Fabrizio

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接