如果对列表进行排序,为什么Delphi的TStringList.InsertObject()方法抛出异常?

时间:2011-05-24 13:39:56

标签: delphi exception sortedlist sorted tstringlist

在Delphi 6中,如果您尝试将对象插入到已排序的TStringList(Sorted = true),则会抛出异常,警告您在排序列表上不允许使用InsertObject()。如果调用InsertObject()必然意味着破坏列表的Sorted顺序,我可以理解这一点。但鉴于TStringList.Find()方法:

function TStringList.Find(const S: string; var Index: Integer): Boolean;

返回一个索引,告诉你如果给定字符串添加到列表中的确切插入索引应该是什么,使用该索引调用InsertObject()应该在操作之后使排序列表保持排序顺序。我已经检查了TStringList的Delphi源代码,它似乎证实了我的断言。

现在我只是为TStringList创建一个新的子类,它覆盖了InsertObject(),并且如果在排序列表上调用了InsertObject(),则不会抛出异常,但我想确保没有隐藏的内容我只是没有看到的危险。

- roschler

5 个答案:

答案 0 :(得分:7)

您应该在排序列表上调用AddObject

如果InsertObject检查了排序列表中的“正确”索引,那么您将面临测试噩梦:在某些情况下,您的代码似乎可以正常工作,但如果输入数据会突然开始抛出异常改变。或者,如果InsertObject忽略Index参数,则其行为将非常不直观。

如果列表已排序,InsertObject总是抛出更好。

答案 1 :(得分:3)

错误消息对我来说非常清楚:不允许在已排序的TStringlist上调用Insert或InsertObject。当sorted为true时,stringlist将自动处理新条目的位置以保持列表的排序。假设允许插入,stringlist如何知道给定索引不会破坏排序?它必须找到正确的索引,将其与给定的索引进行比较,然后呢?使用找到的或抛出异常。因此,只允许使用Add或AddObject。

答案 2 :(得分:2)

为避免复制Find执行的二进制搜索,您可以使用受保护的InsertItem方法:

type
  THackSL = class(TStringList);

...

var
  i: Integer;
  s: string;
begin
  ...
  if not MyStringList.Find(s, i) then
    THackSL(MyStringList).InsertItem(i, s, nil);
 

答案 3 :(得分:1)

不要检查Delphi6,但在Delphi XE中它是相同的。如果列表已排序,则应使用AddObject。当列表为您排序项目时,将对象插入特定位置是没有意义的。

答案 4 :(得分:0)

请改用TStringList.Add。它会自动检查重复项并将字符串插入正确的位置