Supponendo che non sia stato specificato un confronto nel costruttore su TList.Create
, si otterrà TComparer<TSomeRecord>.Default
come comparatore. E questo è un comparatore che esegue un semplice confronto binario usando CompareMem
.
Questo va bene per un record pieno di tipi di valore, senza padding. In caso contrario, dovrai fornire la tua funzione di confronto quando installi l'elenco.
Se si desidera esaminare i dettagli, il confronto predefinito per i record è implementato in Generics.Defaults
. Per i record più grandi il confronto di uguaglianza è questa funzione:
function Equals_Binary(Inst: PSimpleInstance; const Left, Right): Boolean;
begin
Result := CompareMem(@Left, @Right, Inst^.Size);
end;
per i record più piccoli c'è un'ottimizzazione e il vostro operatore di confronto sarà l'operatore di confronto 4 byte. Che assomiglia a questo:
function Equals_I4(Inst: Pointer; const Left, Right: Integer): Boolean;
begin
Result := Left = Right;
end;
Questo è un po 'strano, ma interpreta i 4 byte di vostro record come un intero 4 byte ed esegue confronto di uguaglianza intero. In altre parole, lo stesso di CompareMem
, ma più efficiente.
L'operatore di confronto che si desidera utilizzare potrebbe essere simile a questo:
TComparer<TSomeRecord>.Construct(
function const Left, Right: TSomeRecord): Integer
begin
Result := CompareStr(Left.Value, Right.Value);
end;
)
Usa CompareText
se si vuole case insensitive, e così via. Ho usato una funzione di confronto ordinata perché è ciò che vuole TList<T>
.
Il fatto che il confronto dei record predefinito sia un confronto di uguaglianza indica che i tentativi di ordinare elenchi di record senza specificare il proprio comparatore avranno risultati imprevisti.
Dato che l'operatore di confronto di default utilizza un confronto di uguaglianza ti dice che non sarebbe del tutto irragionevole utilizzare un operatore di confronto come questo:
TComparer<TSomeRecord>.Construct(
function const Left, Right: TSomeRecord): Integer
begin
Result := ord(not (Left = Right));
end;
)
Questo andrà bene per le operazioni non ordinate come IndexOf
o Contains
ma ovviamente non utilizzare affatto per l'ordinamento, la ricerca binaria e così via.
Come funziona l'impl Pari operatore assomigliano? Potrebbe essere correlato a http: // StackOverflow.it/questions/8862807/list-and-contiene-method –
In generale, i record non supportano l'operatore '=', ed è impossibile rilevare in codice se un particolare tipo lo supporta, quindi l'implementazione di default deve usare il confronto della memoria semplice per tutti i tipi che non ha * a priori * conoscenza di. –
Grazie a @RobKennedy, sarebbe bello avere un vincolo di uguaglianza sui tipi generici che garantirebbe l'esistenza di un operatore di uguaglianza. – jpfollenius