Ошибка переполнения стека с Generic TList.Sort

Я реализовал Generics.Defaults.TComparer для сортировки типизированного TList. Однако при вызове метода Sort выдается исключение "Переполнение стека в..."

Почему возникает ошибка переполнения стека?

// Declarations

  TOrder = record
    ID: Integer;
    OrderDate: TDate;
  end;

  POrder = ^TOrder;

  FOrderList: TList<POrder>;

  TComparer_OrderDate = class(TComparer<POrder>)
  public
    function Compare(const a, b: POrder): Integer; override;
  end;

function TComparer_OrderDate.Compare(const a, b: POrder): Integer;
begin
  Result := 0;

  if (a^.OrderDate> b^.OrderDate) then
    Result := 1
  else
    Result := -1;
end;


  // This code inside a button OnClick event: 
  FOrderList := TList<POrder>.Create;

  FComparer_OrderDate := TComparer_OrderDate.Create;

  FOrderList.Sort(FComparer_OrderDate); // <--- 'stack overflow' error.

person Steve F    schedule 06.02.2016    source источник
comment
Возможный дубликат Как мне отсортировать общий список использовать пользовательский компаратор?   -  person fantaghirocco came to Rome    schedule 06.02.2016
comment
Ok. Я использовал Result := TComparer‹Integer›.Default.Compare(a^.ID, b^.ID); и это, кажется, работает. Почему это?   -  person Steve F    schedule 06.02.2016
comment
Почему вы сортируете по дате в вопросе, а по идентификатору в комментарии?   -  person David Heffernan    schedule 07.02.2016


Ответы (1)


Ваша функция сравнения должна возвращать 0 для равенства. Так:

function TComparer_OrderDate.Compare(const a, b: POrder): Integer;
begin  
  if (a^.OrderDate > b^.OrderDate) then
    Result := 1
  else if (a^.OrderDate < b^.OrderDate) then
    Result := -1
  else
    Result := 0;
  end;
end;

Для сравнения проще использовать TComparer<POrder>.Construct.

FOrderList.Sort(
  TComparer<POrder>.Construct(
    function(const a, b: POrder): Integer
    begin  
      if (a^.OrderDate > b^.OrderDate) then
        Result := 1
      else if (a^.OrderDate < b^.OrderDate) then
        Result := -1
      else
        Result := 0;
      end;
    end
  )
);

Или используйте компаратор времени по умолчанию:

DateTimeComparer := TComparer<TDateTime>.Default;
FOrderList.Sort(
  TComparer<POrder>.Construct(
    function(const a, b: POrder): Integer
    begin  
      Result := DateTimeComparer.Compare(a^.OrderDate, b^.OrderDate);
    end
  )
);

Я ничего из этого не компилировал, поэтому ожидаю, что будут небольшие ошибки.

person David Heffernan    schedule 06.02.2016