Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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

like image 915
Robert Oschler Avatar asked May 24 '11 13:05

Robert Oschler


4 Answers

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.

like image 127
Roddy Avatar answered Nov 01 '22 18:11

Roddy


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.

like image 33
Uwe Raabe Avatar answered Nov 01 '22 18:11

Uwe Raabe


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);
 
like image 23
Sertac Akyuz Avatar answered Nov 01 '22 16:11

Sertac Akyuz


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.

like image 1
Mikael Eriksson Avatar answered Nov 01 '22 17:11

Mikael Eriksson