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)