2

我有一个简单的应用程序,它尝试使用 String.Compare 比较 2 个字符串。我遇到了一种情况,当我向每个字符串添加更多值时,答案会发生变化。

取这两个字符串:

---a
--1S

当比较字符串中越来越多的值时,String.Compare 显示以下结果:

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

为什么它会改变答案?一旦到达第三个位置,它应该保持 -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。)请参阅此线程标题的命题。附加到字符串会颠倒它们的顺序。为什么?

新增:似乎没有指定序数比较 or CompareOptions.StringSort,算法是:首先-从两个字符串中删除所有连字符( )。如果之后一个大于另一个,则返回该答案。(否则,请再次考虑连字符...)使用"---"and "--1",删除连字符以获得""and "1"。它们仍然不同,第一个是最少的。返回减一。但是,使用"---a"and "--1S",调用比较"a"and "1S",现在第一个是最大的,它返回加一。

顺便说一句,这个问题非常相似:string.Compare behavior

于 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

于 2012-09-11T20:17:18.810 回答