String.Compare答案更改,因为chracters被添加到字符串的末尾

时间:2012-09-11 20:12:48

标签: c# .net string

我有一个简单的应用程序尝试使用String.Compare比较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 个答案:

答案 0 :(得分:2)

如果您没有传递CultureInfo,则String.Compare的比较将基于当前的线索文化,其可能具有与您预期不同的比较规则。 String.CompareOrdinal仅比较代码点,而不考虑文化。

换句话说,请尝试将this overloadCultureInfo.InvariantCulture一起使用。

这是进行不同比较的原因。

答案 1 :(得分:0)

为了让String.Compare方法按照我的预期处理非字母数字值,我需要提供CultureInfo以及ComparOptions Enum值。

如下所示,重写问题示例中的第一个方法会产生所需的结果:

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

CompareOptions.StringSort“表示字符串比较必须使用字符串排序算法。在字符串排序中,连字符和撇号以及其他非字母数字符号位于字母数字字符之前。”

感谢大家指出了导致CultureInfo的{​​{1}}路径。

答案 2 :(得分: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,算法是:首先从两个字符串中删除所有连字符(-)。如果之后一个大于另一个,则返回该答案。 (否则,请再次考虑连字符......)对于"---""--1",请删除连字符以获取"""1"。他们仍然不同,第一个是最少的。返回减1。但是,对于"---a""--1S",调用会比较"a""1S",现在第一个是最大的,并返回加1。

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

答案 3 :(得分:-1)

只是为了澄清你知道答案在右边,对吗?

如果不进行比较,它将小于或大于0,如果不进行比较则为0