6

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

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

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

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

——罗施勒

4

5 回答 5

7

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

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

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

于 2011-05-24T13:50:19.963 回答
3

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

于 2011-05-24T13:50:47.087 回答
2

为避免重复执行的二分查找Find,可以使用 protectedInsertItem方法:

type
  THackSL = class(TStringList);

...

var
  i: Integer;
  s: string;
begin
  ...
  if not MyStringList.Find(s, i) then
    THackSL(MyStringList).InsertItem(i, s, nil);
 
于 2011-05-24T15:58:40.170 回答
1

无需检查 Delphi6,但在 Delphi XE 中是相同的。如果列表已排序,则应改用 AddObject。当列表为您排序项目时,在特定位置插入对象实际上没有意义。

于 2011-05-24T13:50:15.527 回答
0

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

于 2011-05-24T13:59:46.370 回答