コンストラクターで比較子を指定しなかったと仮定すると、比較子としてTList.Create
取得TComparer<TSomeRecord>.Default
されます。そして、それは を使用して単純なバイナリ比較を実行する比較子ですCompareMem
。
パディングなしで、値の型でいっぱいのレコードには問題ありません。ただし、それ以外の場合は、リストをインスタンス化するときに独自の比較関数を提供する必要があります。
詳細を確認したい場合は、レコードのデフォルトの比較機能が に実装されていGenerics.Defaults
ます。より大きなレコードの場合、等値比較子は次の関数です。
function Equals_Binary(Inst: PSimpleInstance; const Left, Right): Boolean;
begin
Result := CompareMem(@Left, @Right, Inst^.Size);
end;
小さいレコードの場合は最適化が行われ、比較子は 4 バイトの比較子になります。それは次のようになります。
function Equals_I4(Inst: Pointer; const Left, Right: Integer): Boolean;
begin
Result := Left = Right;
end;
これは少し奇妙ですが、レコードの 4 バイトを 4 バイトの整数として解釈し、整数の等価比較を実行します。つまり、 と同じCompareMem
ですが、より効率的です。
使用する比較子は次のようになります。
TComparer<TSomeRecord>.Construct(
function const Left, Right: TSomeRecord): Integer
begin
Result := CompareStr(Left.Value, Right.Value);
end;
)
CompareText
大文字と小文字を区別しない場合などに使用します。それが必要なので、順序付き比較関数を使用しましたTList<T>
。
デフォルトのレコード比較が等価比較であるという事実は、独自の比較子を指定せずにレコードのリストをソートしようとすると、予期しない結果になることを示しています。
デフォルトの比較子が等価比較を使用することを考えると、次のような比較子を使用することはまったく不合理ではないことがわかります。
TComparer<TSomeRecord>.Construct(
function const Left, Right: TSomeRecord): Integer
begin
Result := ord(not (Left = Right));
end;
)
IndexOf
orのような順序付けられていない操作には問題Contains
ありませんが、並べ替えや二分探索などにはまったく使用されません。