在阅读了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
答案 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>;