我想在列表中存储按名称排序的对象。应忽略重复项,添加后应自动释放对象。在pre-generics时代,我会使用这样的TStringList:
List := TStringList.Create;
List.Sorted := true;
List.Duplicates := dupIgnore;
List.AddObject('bla', TSomeObject.Create({parameters go here});
List.AddObject('blub', TSomeObject.Create({parameters go here});
List.AddObject('bla', TSomeObject.Create({parameters go here});
(插入'bla'两次会造成内存泄漏,我知道,这是我想在这里解决的一个问题。)
由于Delphi现在带有多个通用容器,我认为应该有一个使上面更清洁的容器。
我提出的第一个是TDictionary:
type
TSomeObjectContainer = TDictionary<string, TSomeObject>
// etc.
不幸的是TSomeObjectContainer不允许我忽略重复项,因此我必须自己实施该检查。
我错过了什么吗?
答案 0 :(得分:5)
如果我看到您要查找的内容,使用TDictionary&lt;&gt; .AddOrSetValue()可以帮助重复。此外,TObjectDictionary类似乎可以帮助您进行内存管理。
一个例子(导致我的测试没有泄漏):
Dict := TObjectDictionary<string, TObject>.Create([doOwnsValues]);
try
Dict.AddOrSetValue('c', TObject.Create);
Dict.AddOrSetValue('c', TObject.Create);
Dict.AddOrSetValue('d', TObject.Create);
finally
Dict.Free;
end;
答案 1 :(得分:1)
你可以这样做:
TSomeObjectContainer = TDictionary<string, TSomeObject>;
procedure AddAndFreeDuplicates(aKey: string; aValue: TSomeObject);
end;
procedure TSomeObjectContainer.AddAndFreeDuplicates(aKey: string; aValue: TSomeObject);
begin
if Self.ContainsKey(aKey) then
aValue.Free
else
Self.Add(aKey, aValue);
end;
然后使用它你会做这样的事情:
var
MyCont: TSomeObjectContainer;
begin
MyCont := TSomeObjectContainer.Create;
MyCont.AddAndFreeDuplicates('bla', TSomeObject.Create({parameters go here}));
MyCont.AddAndFreeDuplicates('blub', TSomeObject.Create({parameters go here}));
MyCont.AddAndFreeDuplicates('bla', TSomeObject.Create({parameters go here}));
...
MyCont.Free;
end;
这取决于您添加的频率以及列表中有多少项目是否应创建列表并保持其排序。最终,您将不得不在添加时检查重复项。问题是你如何进行检查。
答案 2 :(得分:0)
遗憾的是,没有通用的TStringList。对于这样的案例,你最好的选择是建立在你最初的想法上:创建一个继承自TDictionary<string, TSomeObject>
的类,并放入你自己的Add
方法,检查重复项并适当地处理它们,或调用inherited
如果没有。{/ p>
答案 3 :(得分:0)
你没有遗漏任何东西。当前的Generic容器集没有您正在寻找的功能。没有通用容器可以执行TStringList
所做的一切,因此您必须自己实现某些功能。如果您使用TDictionary
,则必须自行实施重复检查。如果您使用TList<T>
或TObjectList<T>
,则必须实施自己的排序和重复检查。