Nou ja, gewoon...
Met een generic TList<> moet je een comparer interface meegeven. Gelukkig is dat ook vrij simpel:
Delphi Code:
TGegevensComparer = class(TInterfacedObject, IComparer<TGegevens>)
private function Compare(const Left, Right: TGegevens): Integer;
end;
{ TGegevensComparer }
function TGegevensComparer.Compare(const Left, Right: TGegevens): Integer;
begin
Result := Left.A - Right.A;
if Result <> 0 then Exit;
Result := Left.B - Right.B;
if Result <> 0 then Exit;
Result := Left.C - Right.C;
if Result <> 0 then Exit;
Result := CompareText(Left.data, Right.data); // indien wenselijk
end;
Maar dan komt er nog een valkuiltje. De verleiding is groot om het zo aan te roepen:
Delphi Code:
Lijst.Sort(TGegevensComparer.Create);
Helaas heeft Delphi een 'optimalisatie', die ervoor zorgt dat er geen AddRef aangeroepen wordt, als je op deze manier een class instantieert, en die in de method-aanroep impliciet naar interface typecast. Dit levert dus een memory leak op, omdat de TGegevensComparer nooit vrijgegeven wordt.
Je moet de gemaakte comparer dus expliciet typecasten naar interface om de AddRef te forceren. Dat betekent: eerst toekennen aan een variabele van het type `IComparer<TGegevens>`, of expliciet typecasten in de aanroep.
Delphi Code:
Lijst.Sort((TGegevensComparer.Create) as IComparer<TGegevens>);
Mocht je 'gewoon' een inline function mee willen geven, dan heb je ook pech. TList heeft zelf geen overload waarmee dat kan. Dat is uitbesteed aan een implementatie van ICompare<T>: de TDelegatedComparer<>. Die heeft een constructor waaraan je de comparer function (al dan niet inline) mee kan geven.
Maar die heeft dus ook hetzelfde typecast issue, dus de aanroep wordt dan zo, verre van elegant:
Delphi Code:
Lijst.Sort(
( TDelegatedComparer<TGegevens>.Create(
function (const Left, Right: TGegevens): Integer
begin
Result := Left.A - Right.A;
if Result <> 0 then Exit;
Result := Left.B - Right.B;
if Result <> 0 then Exit;
Result := Left.C - Right.C;
if Result <> 0 then Exit;
Result := CompareText(Left.data, Right.data);
end
)) as IComparer<TGegevens>);
Bookmarks