如何在Delphi中调用TObjectDictionary的继承构造函数

时间:2013-04-12 14:20:55

标签: delphi generics constructor inherited

在阅读了TDictionary对TStringList的显着性能改进之后,我创建了以下类:

    TAnsiStringList = class(TObjectDictionary<AnsiString,TObject>)
    public
      constructor Create(const OwnsObjects: Boolean = True); reintroduce;
      destructor Destroy; override;
      procedure Add(const AString: AnsiString);
      procedure AddObject(const AString: AnsiString; AObject: TObject);
    end;

我将构造函数编码为:

  { TAnsiStringList }

    constructor TAnsiStringList.Create(const OwnsObjects: Boolean = True);
    begin
      if OwnsObjects then
        inherited Create([doOwnsKeys,doOwnsValues])
      else
        inherited Create;
    end;

...期望调用这个TObjectDictionary构造函数:

    constructor Create(Ownerships: TDictionaryOwnerships; ACapacity: Integer = 0); overload;

...如果指定了Ownerships参数。如果未指定Ownerships参数,我预计将调用以下继承的TDictionary构造函数:

    constructor Create(ACapacity: Integer = 0); overload;

代码编译并运行,但是当我调用

    inherited Create([doOwnsKeys,doOwnsValues]) I get the following error:

无效的类别转换

有没有人看到我做错了什么,有没有正确的方法来做到这一点?

TIA

1 个答案:

答案 0 :(得分:4)

问题是,当您删除项目时,您要求容器在您的密钥上调用Free。但是你的密钥不是类,所以这是一个无效的请求。这是在运行时而不是编译时捕获的,因为直到运行时才确定所有权。

您只需要doOwnsValues,并且应该删除doOwnsKeys

 if OwnsObjects then
    inherited Create([doOwnsValues])
 else
   inherited Create;

值得一提的是,如果你想要AnsiString相当于TStringList,那么你的方法是有缺陷的。字符串列表是有序容器,但字典不是。您将无法按整数索引,按顺序迭代等等。我也不明白为什么你想强迫这个类的所有使用者声明对象是TObject类型。您应该保留该参数,供消费者指定。这就是仿制药之美。

也许你不想要一个有序的容器,在这种情况下你需要一本字典。但在这种情况下,您根本不需要创建新类。您可以按原样使用TObjectDictionary

如果您在创建子类时已经死定,那么我会这样做:

type
  TAnsiStringDict<T: class> = class(TObjectDictionary<AnsiString, T>)

这将允许类的使用者决定他们将哪些类型的对象放入字典中,并保持编译时类型的安全性。

所以,当你想要一个列表框字典时,你要声明一个这样的变量:

var
  ListBoxDict: TAnsiStringDict<TListBox>;