Почему Tstringlist Delphi.Метод InsertObject () создает исключение, если список отсортирован?

в Delphi 6 при попытке вставить объект в сортируемый список TStringList (Sorted = true) создается исключение, предупреждающее, что InsertObject () не разрешен в отсортированном списке. Я мог бы понять это, если вызов InsertObject () обязательно означал уничтожение отсортированного порядка списка. Но учитывая, что TStringList.Метод Find ():

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

возвращает индекс, указывающий, каким должен быть индекс вставки для данной строки, если она была добавлена в список, вызов InsertObject () с этим индексом должен оставить отсортированный список все еще в отсортированном порядке после операции. Я изучил источник Delphi для TStringList и, похоже, подтверждает мое утверждение.

пока я просто создаю новый подкласс для TStringList, который переопределяет InsertObject() и не создает исключение, если InsertObject () вызывается в отсортированном списке, но я хочу убедиться, что нет какой-то скрытой опасности, которую я просто не вижу.

-- roschler

5 ответов


позвони AddObject вместо этого в отсортированном списке.

если InsertObject проверено на "правильный" индекс в отсортированных списках, тогда у вас будет кошмар тестирования: при некоторых обстоятельствах ваш код будет работать, но внезапно начнет выбрасывать исключения, если входные данные изменятся. Или, если InsertObject игнорировать Index параметр, тогда его поведение было бы дико неинтуитивным.

это намного лучше для InsertObject всегда бросать, если список сортированный.


сообщение об ошибке кажется мне очень ясным: не разрешается вызывать Insert или InsertObject в отсортированном TStringlist. Если сортировка имеет значение true, stringlist автоматически обрабатывает позицию новой записи, чтобы сохранить сортировку списка. Предполагая, что вставка разрешена, как stringlist может знать, что данный индекс не нарушает сортировку? Он должен был бы найти правильный индекс, сравнить его с данным, а затем? Либо используйте найденный, либо создайте исключение. Таким образом, только добавить или Методы addObject допускается.


чтобы избежать дублирования двоичного поиска, выполняемого 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);
 

нет Delphi6 для проверки, но это то же самое в Delphi XE. Если список отсортирован, вместо него следует использовать AddObject. На самом деле нет смысла вставлять объект в определенную позицию, когда список сортирует элементы для вас.


Используйте TStringList.Вместо этого добавьте. Он автоматически проверит наличие дубликатов и вставит строку в нужное место