StringComparison.OrdinalIgnoreCaseの戻り値はどうあるべきですか?

Aug 24 2020

以下の行を実行すると

returnVal=string.Compare("stringOne","stringTwo",StringComparison.OrdinalIgnoreCase);

returnValを-5として取得します。なぜそんなことなのか説明してもらえますか?また、他の文字列値では、13,15などの戻り値を取得します。通常は-1,0,1である必要があります。私が間違っていなければ。

回答

1 RufusL Aug 24 2020 at 21:38

「通常は-1,0,1である必要があります。私が間違っていなければ」

これらは通常、Compareメソッドの戻り値であり、次のドキュメントでも推奨される方法であることが正しいですIComparer.Compare

https://docs.microsoft.com/en-us/troubleshoot/dotnet/csharp/use-icomparable-icomparer

IComparer.Compare方法は、第三の比較を必要とする10または-1他の以下に等しい、または、一つの値がより大きいか否かに応じて返される。ソート順(昇順または降順)をこの方法で論理演算子を切り替えることにより変更することができます。」

ただし、これはどこにも適用されません。

また、Stringクラスはを実装せずIComparer<string>Compare署名のこのオーバーロードはとにかくそのインターフェイスで定義されていません。

ここでCompareメソッドのソースコードを見ると、の場合、メソッドが呼び出され、一致しない文字の最初のペア間のASCII値の差が返されます(大文字にした後)。文字列の長さが異なるが、長い方の最初の文字がすべて短い方の文字と一致する場合、長さの差が返されます。OrdinalIgnoreCaseCompareOrdinalIgnoreCaseHelper

private unsafe static int CompareOrdinalIgnoreCaseHelper(String strA, String strB)
{
    Contract.Requires(strA != null);
    Contract.Requires(strB != null);
    Contract.EndContractBlock();
    int length = Math.Min(strA.Length, strB.Length);

    fixed (char* ap = &strA.m_firstChar) fixed (char* bp = &strB.m_firstChar)
    {
        char* a = ap;
        char* b = bp;

        while (length != 0) 
        {
            int charA = *a;
            int charB = *b;

            Contract.Assert((charA | charB) <= 0x7F, "strings have to be ASCII");

            // uppercase both chars - notice that we need just one compare per char
            if ((uint)(charA - 'a') <= (uint)('z' - 'a')) charA -= 0x20;
            if ((uint)(charB - 'a') <= (uint)('z' - 'a')) charB -= 0x20;

            //Return the (case-insensitive) difference between them.
            if (charA != charB)
                return charA - charB;

            // Next char
            a++; b++;
            length--;
        }

        return strA.Length - strB.Length;
    }
}

したがって、我々は常に結果を比較すべきであるCompareと方法を0していません-11