2

String.Compare を使用して 2 つの文字列を比較しようとする単純なアプリケーションがあります。各文字列に値を追加すると、答えが変わる状況に遭遇しました。

次の 2 つの文字列を使用します。

---a
--1S

String.Compare は、文字列内の値の増加を比較すると、次の結果を示します。

String.Compare
   -:   -   0
  --:  --   0
 ---: --1  -1
---a:--1S   1

なぜ答えを変えるのですか?文字列に追加された追加の値に関係なく、3 番目の位置に到達すると、-1 のままになります。

一方、 はString.CompareOrdinalこれに同意し、すべての文字列の長さに対して < 0 のままです。

これらの結果を示すサンプル プログラムを次に示します。

using System;

namespace TestFileMerge
{
    public static class Program
    {
        public static void Main(string[] args)
        {
            const string value1 = "---a";
            const string value2 = "--1S";
            Console.WriteLine("String.Compare");
            for (int i = 1; i <= value1.Length; i++)
            {
                Console.WriteLine(
                    @"{0}:{1} {2}", 
                    value1.Substring(0, i).PadLeft(value2.Length), 
                    value2.Substring(0, i).PadLeft(value2.Length), 
                    String.Compare(
                        value1.Substring(0, i), 
                        value2.Substring(0, i),
                        false
                    ).ToString().PadLeft(3));
            }
            Console.WriteLine("String.Compare -- ignore case");
            for (int i = 1; i <= value1.Length; i++)
            {
                Console.WriteLine(
                    @"{0}:{1} {2}", 
                    value1.Substring(0, i).PadLeft(value2.Length), 
                    value2.Substring(0, i).PadLeft(value2.Length), 
                    String.Compare(
                        value1.Substring(0, i), 
                        value2.Substring(0, i),
                        true
                    ).ToString().PadLeft(3));
            }
            Console.WriteLine("String.CompareOrdinal");
            for (int i = 1; i <= value1.Length; i++)
            {
                Console.WriteLine
                    (@"{0}:{1} {2}", 
                    value1.Substring(0, i).PadLeft(value2.Length), 
                    value2.Substring(0, i).PadLeft(value2.Length), 
                    String.CompareOrdinal(
                        value1.Substring(0, i), 
                        value2.Substring(0, i)
                    ).ToString().PadLeft(3));
            }
        }
    }
}

これにより、次の出力が生成されます。

String.Compare
   -:   -   0
  --:  --   0
 ---: --1  -1
---a:--1S   1
String.Compare -- ignore case
   -:   -   0
  --:  --   0
 ---: --1  -1
---a:--1S   1
String.CompareOrdinal
   -:   -   0
  --:  --   0
 ---: --1  -4
---a:--1S  -4
4

4 に答える 4

2

を渡さない場合CultureInfo、 の比較String.Compareは現在のスレッド カルチャに基づいて行われ、予想とは異なる比較規則が適用される可能性があります。String.CompareOrdinalカルチャを考慮せずに、コード ポイントのみを比較します。

つまり、このオーバーロードを で使用してみてくださいCultureInfo.InvariantCulture

これが異なる比較の理由です。

于 2012-09-11T20:18:29.197 に答える
0

変な行動だと思います。次のことを考慮してください

static void Test()
{
        Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;
        const string a = "-";
        const string b = "1";

        Console.WriteLine(String.Compare(a, b));                  // -1
        Console.WriteLine(String.Compare(a + "x", b + "x"));      // +1
}

同じ定数を右側"x"に連結すると、文字列の順序が逆になるのはなぜですか? ご覧のとおり、これは不変の文化にあります。

インバリアント カルチャとString.Compare(String, String)オーバーロードに従って、次の文字列のリストは昇順に並べ替えられます。

""
"-"
"--"
"1"
"1-"
"-1"
"11"
"1x"
"1y"
"x"
"x-"
"-x"
"x1"
"xx"
"xy"
"y"
"y-"
"-y"
"y1"
"yx"
"yy"

推移性の違反は見つかりませんでした。しかし、一番左の文字の「列」を読むと、マイナスが非常に遅く表示されるのは奇妙に思えます。

追加:冗長オーバーロードの使用を主張する人のための最初の例:

String.Compare("-", "1", CultureInfo.InvariantCulture, CompareOptions.IgnoreCase);   // -1
String.Compare("-x", "1x", CultureInfo.InvariantCulture, CompareOptions.IgnoreCase); // +1

( などでも動作しCompareOptions.Noneます。) このスレッドのタイトルの命題を参照してください。文字列に追加すると、順序が逆になります。なんで?

新規追加:序数比較 または を指定しないと、アルゴリズムは次のようになります: まず、両方の文字列からCompareOptions.StringSortすべてのハイフン ( ) を削除します。-その後、一方が他方より大きい場合は、その答えを返します。(それ以外の場合は、ハイフンをもう一度検討してください...) "---"and"--1"で、ハイフンを削除して and を取得"""1"ます。それらはまだ異なり、最初のものは最小です。マイナス 1 を返します。ただし、 and を使用する"---a""--1S"、呼び出しは and を比較"a""1S"、最初の値が最大になり、プラス 1 を返します。

ところで、この質問は非常に似ています: string.Compare 動作

于 2012-09-11T21:13:47.893 に答える
0

String.Compare英数字以外の値を期待どおりに処理するメソッドを取得するにはCultureInfo、値だけでなく も提供する必要がありましたComparOptions Enum

質問の例の最初のメソッドを次のように書き直すと、望ましい結果が得られます。

String.Compare(
    value1.Substring(0, i), 
    value2.Substring(0, i),
    CultureInfo.CurrentCulture,
    CompareOptions.StringSort
}

CompareOptions.StringSort文字列比較で文字列並べ替えアルゴリズムを使用する必要があることを示します。文字列並べ替えでは、ハイフンとアポストロフィ、およびその他の英数字以外の記号が英数字の前に来ます。」

CultureInfoこれに至るまでの道のりを教えてくれたすべての人に感謝しますEnum

于 2012-09-11T20:49:52.590 に答える
-1

明確にするために、答えが右側にあることを知っていますよね?

比較しない場合は 0 未満または 0 より大きくなり、比較する場合は 0 になります。

于 2012-09-11T20:17:18.810 に答える