如果列表已排序,为什么 Delphi 的 TStringList.InsertObject() 方法会抛出异常?
在 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() 则不会抛出异常,但我想确保不存在一些隐藏的危险我只是没看到。
——罗施勒
In Delphi 6 if you try to insert an object into a TStringList that is sorted (Sorted = true) an Exception is thrown warning you that InsertObject() is not allowed on a sorted list. I could understand this if calling InsertObject() necessarily meant destroying the Sorted order of the list. But given that the TStringList.Find() method:
function TStringList.Find(const S: string; var Index: Integer): Boolean;
returns an index telling you exactly what the insertion index should be for a given string if it were added to the list, calling InsertObject() with that index should leave the sorted list still in sorted order after the operation. I've examined the Delphi source for TStringList and it seems to bear out my assertion.
For now I'm just creating a new sub-class for TStringList that overrides InsertObject() and does not throw an Exception if InsertObject() is called on sorted list, but I want to make sure there isn't some hidden danger that I'm just not seeing.
-- roschler
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
您应该只在排序列表上调用
AddObject
。如果
InsertObject
检查排序列表上的“正确”索引,那么您将遇到一个测试噩梦:在某些情况下,您的代码似乎可以工作,但如果输入数据会突然开始抛出异常改变了。或者,如果InsertObject
忽略了Index
参数,那么它的行为将非常不直观。如果列表已排序,
InsertObject
最好总是抛出异常。You should just call
AddObject
instead on a sorted list.If
InsertObject
checked for the 'correct' index on sorted lists, then you'd have a testing nightmare: Under some circumstances, your code would appear to work, but would suddenly start throwing exceptions if the input data changed. Or, ifInsertObject
ignored theIndex
parameter, then its behaviour would be wildly non-intuitive.It's much better for
InsertObject
to always throw if the list is sorted.错误消息对我来说似乎非常清楚:不允许在已排序的 TStringlist 上调用 Insert 或 InsertObject。当sorted为true时,字符串列表将自动处理新条目的位置以保持列表排序。假设允许插入,字符串列表如何知道给定的索引不会破坏排序?它必须找到正确的索引,将其与给定的索引进行比较,然后呢?要么使用找到的一个,要么抛出异常。因此只允许添加或添加对象。
The error message seems very clear to me: it is not allowed to call Insert or InsertObject on a sorted TStringlist. When sorted is true, the stringlist will automatically handle the position of the new entry to keep the list sorted. Assuming Insert were allowed, how could the stringlist know that the given index doesn't break the sorting? It would have to find the correct index, compare it with the given one and then? Either use the found one or throw an exception. Thus only Add or AddObject is allowed.
为了避免重复由
Find
执行的二分搜索,您可以使用受保护的InsertItem
方法:To avoid to duplicate the binary search carried out by
Find
, you can use the protectedInsertItem
method:没有Delphi6可以检查,但在Delphi XE中是一样的。如果列表已排序,您应该使用 AddObject。当列表为您对项目进行排序时,在特定位置插入对象实际上没有意义。
Don't have Delphi6 to check but it is the same in Delphi XE. If the list is sorted you should use AddObject instead. Does not really make sense to insert an object at a specific position when the list is sorting the items for you.
请改用 TStringList.Add。它会自动检查重复项并将字符串插入到正确的位置
Use TStringList.Add instead. It will automatically check for duplicates and insert the string in the right place