Talk:Generics Defaults TComparer (Delphi)
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)