Talk:Generics Defaults TComparer (Delphi)

From RAD Studio Code Examples
Jump to: navigation, search

I'm using Delphi XE Pro. I have a crash in custom sort case:

 procedure TForm3.btCustomSortClick(Sender: TObject);
 var
   Cmp : TIntStringComparer;
 begin
   { Use our custom comparer }
   Cmp := TIntStringComparer.Create();
   try
     SortMemos(Cmp);
   finally
     Cmp.free;     // <------ crash is here. 'Invalid pointer operation'
   end;
 end;


Thank you for your input! We're investigating this in RAD-10499.--Denisa Tibeica


The crash above is probably to be expected, as TIntStringComparer inherits ultimately from TInterfacedObject, which is reference counted, and hence disposed before getting to finally. Bottom line, so far as I can see, no need to free comparers that inherit from TComparer. Gwideman 16:13, 20 February 2012 (PST)

page renewal proposal

Because of uncompleteness /inexactitudes, here is my proposal for this page:


start ------------------

This example demonstrates the usage of TComparer.
Four TComparer instances are used:
1. a default comparer for String type: TComparer<String>.Default
2. a binary comparer: TStringComparer.Ordinal
3. a custom TComparer<String> comparer: TIntStringComparer
4. a String comparer constructed with an anonymous TComparison<String> function

Code

program Project1;

{$APPTYPE CONSOLE}

uses
 SysUtils,
 Generics.Defaults,
 Generics.Collections,
 AnsiStrings;

type
 { Declare a new custom comparer. }
 TIntStringComparer = class(TComparer<String>)
 public
   function Compare(const Left, Right: String): Integer; override;
 end;

{ TIntStringComparer }
function TIntStringComparer.Compare(const Left, Right: String): Integer;
var
 LeftTerm, RightTerm: Integer;
begin
 { Transform the strings into integers and perform the comparison. }
 try
   LeftTerm := StrToInt(Left);
   RightTerm := StrToInt(Right);
   Result := LeftTerm - RightTerm;
 except
   on E: Exception do
   begin
     writeln('Not a number!');
     Result := CompareStr(Left, Right);
   end;
 end;
end;

procedure FillListWithStrings(aList: TList<String>);
var
 s: String;
begin
 Writeln('list with strings:');
 aList.Clear;
 aList.AddRange(['didier', 'céline', 'louloute', 'john', 'didiot', 'coe']);
 for s in aList do
   Writeln(s);
end;

procedure FillListWithIntegers(aList: TList<String>);
var
 s: String;
 I: Integer;
begin
 Writeln('list with integers:');
 { Populate the list with random numbers. }
 for I := 0 to 5 do
   aList.Add(IntToStr(Random(5)));
 for s in aList do
   Writeln(s);
end;

var
 Cmp: IComparer<String>;
 List: TList<String>;
 A: Integer;
 s: String;
begin
 { Use our custom comparer. }
 Randomize;

 Writeln('Choose the comparer:');
 Writeln('1 = TComparer<String>.Default (default comparer for String type)');
 Writeln('2 = TStringComparer.Ordinal (binary comparison)');
 Writeln('3 = TIntStringComparer (custom TComparer<String> comparer)');
 Writeln('4 = String comparer constructed with an anonymous TComparison<String> function');
 Readln(A);

 case A of
   1: begin
        // default comparer for String type
        List := TList<String>.Create(TComparer<String>.Default);
        FillListWithStrings(List);
        List.Sort;
      end;
   2: begin
        // binary comparison
        List := TList<String>.Create(TStringComparer.Ordinal);
        FillListWithStrings(List);
        List.Sort;
      end;
   3: begin
        // custom TComparer
        Cmp := TIntStringComparer.Create;
        List := TList<String>.Create(Cmp);
        FillListWithIntegers(List);
        List.Sort;
      end;
   4: begin
        // anonymous TComparison<String> function
        List := TList<String>.Create;
        FillListWithStrings(List);
        List.Sort(TComparer<String>.Construct(function(const Left, Right: String): integer
                                              begin
                                                if (Length(Left) < 2) or (Length(Right) < 2) then
                                                  exit(0);
                                                result := ord(Left[2]) - ord(Right[2]);
                                              end));
      end;
   else exit;
 end;
 Writeln('------------');
 Writeln('Sorted list:');
 for s in List do
   Writeln(s);

 { Free resources. }
 List.Free;
 readln;
end.

Uses

System.Generics.Defaults.TComparer ( fr | de | ja )
System.Generics.Defaults.TStringComparer ( fr | de | ja )
System.Generics.Defaults.TStringComparer.Ordinal ( fr | de | ja )
System.Generics.Defaults.TComparer.Default ( fr | de | ja )
System.Generics.Defaults.TComparer.Compare ( fr | de | ja )
System.Generics.Defaults.TComparer.Construct (new)
System.Generics.Defaults.TComparison (new)