Why does Delphi's TStringList.InsertObject() method thrown an Exception if the list is Sorted?
Asked Answered
A

5

6

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

Apophasis answered 24/5, 2011 at 13:39 Comment(1)
Why don't you just call AddObject and it will get added magically at the right index?Cotsen
C
7

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, if InsertObject ignored the Index parameter, then its behaviour would be wildly non-intuitive.

It's much better for InsertObject to always throw if the list is sorted.

Ciracirca answered 24/5, 2011 at 13:50 Comment(1)
If you want the index for some other reason as well: AddObject returns the index. And to decide whether to add the object at all, based on the index found by yourself, see code Sertac Akyuz.Concomitance
R
3

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.

Rodl answered 24/5, 2011 at 13:50 Comment(0)
M
2

To avoid to duplicate the binary search carried out by Find, you can use the protected InsertItem method:

type
  THackSL = class(TStringList);

...

var
  i: Integer;
  s: string;
begin
  ...
  if not MyStringList.Find(s, i) then
    THackSL(MyStringList).InsertItem(i, s, nil);
 
Meaningless answered 24/5, 2011 at 15:58 Comment(5)
@Robert - You're welcome! But I intended to post this as an answer, not a tip. Did I misunderstood your question? Were you not avoiding the search duplication with your sub-classed string list?Meaningless
Well, not a performance tip really: questioner did use Find already. ;)Concomitance
@Concomitance - Well, he'll use it twice if he calls Add or AddObject after Find.. :)Meaningless
That's kind of my point. If you want to determine the index by yourself firstly (using Find), then this code of Sertac 'should' be used to prevent a double search. But in that case, there is no performance improvement like Sertac says there is. Compared to using AddObject I mean. The only reason to perform the search prior to inserting could be to obtain the index for deciding to insert at all.Concomitance
@Concomitance - OK, agreed, I was comparing Find + Add/AddObject to Find + InsertItem.Meaningless
C
1

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.

Coarse answered 24/5, 2011 at 13:50 Comment(0)
F
0

Use TStringList.Add instead. It will automatically check for duplicates and insert the string in the right place

Fallow answered 24/5, 2011 at 13:59 Comment(1)
Depending on the Duplicates property docwiki.embarcadero.com/VCL/en/Classes.TStringList.DuplicatesImbroglio

© 2022 - 2024 — McMap. All rights reserved.