在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
答案 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。它会自动检查重复项并将字符串插入正确的位置