长度字符串比较与字符比较结果不同...为什么?

11

我在学习C#,但在字符串比较中发现了一些意外情况,不是很理解。

请问有人可以解释一下为什么在下面的代码中,单个字符的比较结果与长度为一个字符的字符串比较结果相反吗?

我原本认为 "9" < "=" 将会是 true(因为数字 '9' 的 Unicode 编码(57)小于 '=' 的 Unicode 编码(61)),但实际上是 false...字符串比较的逻辑是什么,为什么会与比较字符不同呢?

代码:

bool resChComp = '9' < '=';
bool resStrComp = String.Compare("9", "=") < 0;

Console.WriteLine($"\n'9' < '=' : {resChComp}, \"9\" < \"=\" : { resStrComp }");

输出:

'9' < '=' : True, "9" < "=" : False

2
因为 char 是一个隐式整数,结果是简单的数学运算:char1 - char2。字符串通常包含多个字符,而 String.CompareTo 使用不同的规则,这些规则在文档中有提到。 - Tim Schmelter
2
如果您使用StringComparison.Ordinal比较器,您将获得预期的行为。String.Compare("9", "=", StringComparison.Ordinal) - Jonathon Chase
1
顺便说一句,这是一个非常好的问题。 - EJoshuaS - Stand with Ukraine
3个回答

5
默认的字符串比较是按单词排序的。根据文档,.NET Framework 使用了三种不同的排序方式:单词排序、字符串排序和序数排序。单词排序对字符串进行区域敏感比较。某些非字母数字字符可能具有特殊的权重值。例如,连字符(“-”)可能具有非常小的权重值,使得“coop”和“co-op”在排序列表中相邻。字符串排序类似于单词排序,但没有特殊情况。因此,所有非字母数字符号都排在所有字母数字字符之前。序数排序基于字符串的每个元素的Unicode值进行比较。您期望的比较是序数比较,您可以通过在String.Compare重载中使用StringComparison.Ordinal来获得,如下所示:
bool resStrComp = String.Compare("9", "=", StringComparison.Ordinal) < 0;

这将通过使用它们的Unicode值进行比较字符串,就像比较一个字符与另一个字符一样。

2
这是因为默认情况下String.Compare使用单词排序顺序,而不是字符的数值。恰好在使用的文化中,9在排序顺序中位于=之前。 如果您指定了二进制排序规则(即Ordinal),如此处所述,它将按您的预期工作。
bool resStrComp = String.Compare("9", "=", StringComparison.Ordinal) < 0;

0
在字符比较的情况下,字符将被转换为对应于ASCII值的int。数字9的ASCII值为57,而等号的值为61。这意味着字符串比较和字符比较并不完全比较相同的内容(这就是它们可能具有不同结果的原因)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接