0

I've implemented Generics.Defaults.TComparer for sorting a typed TList. However when calling the Sort method, it throws an exception "Stack overflow at..."

Why is the Stack overflow error occurring?

// 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.
3
  • Possible duplicate of How do I sort a generic list using a custom comparer? Commented Feb 6, 2016 at 13:51
  • Ok. I used " Result := TComparer<Integer>.Default.Compare(a^.ID, b^.ID);" and it seems to work. Why is that? Commented Feb 6, 2016 at 13:55
  • Why are you sorting by date in the Q but by ID in the comment? Commented Feb 7, 2016 at 20:30

1 Answer 1

7

Your compare function needs to return 0 for equality. Like this:

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;

It's easier to use TComparer<POrder>.Construct to make a comparer.

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
  )
);

Or use the default date time comparer:

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

I've not compiled any of this so I expect there will be minor errors.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.