是否存在用于存储对象的已排序TStringList的泛型?

时间:2014-05-29 19:24:00

标签: delphi generics

我想在列表中存储按名称排序的对象。应忽略重复项,添加后应自动释放对象。在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不允许我忽略重复项,因此我必须自己实施该检查。

我错过了什么吗?

4 个答案:

答案 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>,则必须实施自己的排序和重复检查。