「正しく」を定義します。
i18nの並べ替えは、ロケールに完全に依存します。したがって、これはバグではないというPA
の
見解に完全に同意します。デフォルトのソート動作は、i18n が適切に機能するように設計されたとおりに機能します。
Gerryが述べているように、TStringList.SortはAnsiCompareStrとAnsiCompareTextを使用します (それがどのように行われるかを数行で説明します)。
しかし: TStringList は柔軟性があり、Sort、CustomSort、CompareStringsを含み、これらはすべて仮想です (したがって、子孫クラスでそれらをオーバーライドできます)
。 さらに、CustomSortを呼び出すときに、独自のCompare関数をプラグインできます。
この回答の最後に、必要なことを行う比較機能があります。
- 大文字と小文字を区別
- ロケールを使用していない
- 文字列の文字の序数値を比較するだけです
CustomSortは次のように定義されます。
procedure TStringList.CustomSort(Compare: TStringListSortCompare);
begin
if not Sorted and (FCount > 1) then
begin
Changing;
QuickSort(0, FCount - 1, Compare);
Changed;
end;
end;
デフォルトでは、Sortメソッドの実装は非常に単純で、StringListCompareStringsというデフォルトのCompare関数を渡します。
procedure TStringList.Sort;
begin
CustomSort(StringListCompareStrings);
end;
そのため、独自のTStringListSortCompare互換のCompareメソッドを定義すると、独自の並べ替えを定義できます。
TStringListSortCompare は、TStringList と、比較する項目を参照する 2 つのインデックスを受け取るグローバル関数として定義されます。
type
TStringListSortCompare = function(List: TStringList; Index1, Index2: Integer): Integer;
独自の実装のガイドラインとしてStringListCompareStringsを使用できます。
function StringListCompareStrings(List: TStringList; Index1, Index2: Integer): Integer;
begin
Result := List.CompareStrings(List.FList^[Index1].FString,
List.FList^[Index2].FString);
end;
したがって、デフォルトでは TStringList.Sort は TList.CompareStrings に従います。
function TStringList.CompareStrings(const S1, S2: string): Integer;
begin
if CaseSensitive then
Result := AnsiCompareStr(S1, S2)
else
Result := AnsiCompareText(S1, S2);
end;
次に、下にある Windows API 関数CompareStringをデフォルトのユーザー ロケールLOCALE_USER_DEFAULTで使用します。
function AnsiCompareStr(const S1, S2: string): Integer;
begin
Result := CompareString(LOCALE_USER_DEFAULT, 0, PChar(S1), Length(S1),
PChar(S2), Length(S2)) - 2;
end;
function AnsiCompareText(const S1, S2: string): Integer;
begin
Result := CompareString(LOCALE_USER_DEFAULT, NORM_IGNORECASE, PChar(S1),
Length(S1), PChar(S2), Length(S2)) - 2;
end;
最後に、必要なCompare関数です。再び制限:
- 大文字と小文字を区別
- ロケールを使用していない
- 文字列の文字の序数値を比較するだけです
これはコードです:
function StringListCompareStringsByOrdinalCharacterValue(List: TStringList; Index1, Index2: Integer): Integer;
var
First: string;
Second: string;
begin
First := List[Index1];
Second := List[Index2];
if List.CaseSensitive then
Result := CompareStr(First, Second)
else
Result := CompareText(First, Second);
end;
Delphi はクローズドではなく、まったく逆です。多くの場合、Delphi は非常に柔軟なアーキテクチャです。
多くの場合、その柔軟性をどこに接続できるかを確認するのは、ほんの少しの調査です。
--jeroen