我有一个简单的应用程序尝试使用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
答案 0 :(得分:2)
如果您没有传递CultureInfo
,则String.Compare
的比较将基于当前的线索文化,其可能具有与您预期不同的比较规则。 String.CompareOrdinal
仅比较代码点,而不考虑文化。
换句话说,请尝试将this overload与CultureInfo.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