C# 字符串比较不适用于尾部斜杠
C# String Compare not working with trailing slash
在 C# 4.0 中,每当我比较两个尾部有一个或多个斜杠的字符串时,比较都会给出错误的结果:
String a = "1/2.1/";
String b = "1/2/";
if (a.CompareTo(b) > 0)
MessageBox.Show("Correct: " + a + " > " + b);
else
MessageBox.Show("Not correct: " + a + " <= " + b);
a = a.TrimEnd('/');
b = b.TrimEnd('/');
if (a.CompareTo(b) > 0)
MessageBox.Show("Trailing slash removed. Correct: " + a + " > " + b);
else
MessageBox.Show("Trailing slash removed. Not correct: " + a + " <= " + b);
从词汇上讲,“1/2.1/”在“1/2/”之后,没有太多疑问。
这种行为也发生在其他地方,例如使用 Select 方法对数据表进行排序。
我是不是做错了什么?或者这是 .Net 中的错误?
它甚至不应该与文化特定信息等有任何关系,因为斜线是最基本的美国 ASCII 字符集的一部分。
在比较 SQL 服务器 hierarchyID 时,我 运行 喜欢这个。很容易解决,但这是一个有点令人惊讶的问题。
如果我在 C 中的旧技能没有让我失望,我认为 CompareTo 会逐个字符地减去字符的整数值,直到结果不为零。
在前 3 个相同的字符之后,CompareTo 查看第四个字符,这是第一个字符串的点和第二个字符串的斜线。
点字符的整数值为46,斜杠的整数值为47,46-47返回-1,所以"1/2.1/"小于"1/2/"。
Lexically speaking, "1/2.1/" comes after "1/2/", and there is not much question about that.
为什么会在后面呢?在 ASCII chart 上,/
紧跟在 .
之后。
给定以下两个字符串,在到达第 4 个字符之前它们是相等的。然后比较/
和.
,/
更大。所以您看到的结果 (a < b
) 实际上是正确的。
1/2.1/
1/2/
调用 TrimEnd()
后,您最终得到两个不同的字符串,其中和 a > b
.
1/2.1
1/2
如果数字右对齐,您可以比较包含数字的字符串:
01/02.00/
01/02.10/
01/10.00/
如果这不可能,请考虑为您的数字创建一个类型
public class ChapterNumber : IComparable<ChapterNumber>
{
private readonly decimal[] _number;
public ChapterNumber(params decimal[] number)
{
_number = number;
}
public int CompareTo(T obj)
{
var other = obj as ChapterNumber;
if (other == null) {
return +1;
}
int len = Math.Min(_number.Length, other._number.Length);
for (int i = 0; i < len; i++) {
int result = _number[i].CompareTo(other._number[i]);
if (result != 0) {
return result;
}
}
return _number.Length.CompareTo(other._number.Length);
}
public override ToString()
{
return String.Join('/', _number) + "/";
}
}
用法:
var a = new ChapterNumber(1, 2.1m);
var b = new ChapterNumber(1, 2);
if (a.CompareTo(b) > 0) {
...
}
在 C# 4.0 中,每当我比较两个尾部有一个或多个斜杠的字符串时,比较都会给出错误的结果:
String a = "1/2.1/";
String b = "1/2/";
if (a.CompareTo(b) > 0)
MessageBox.Show("Correct: " + a + " > " + b);
else
MessageBox.Show("Not correct: " + a + " <= " + b);
a = a.TrimEnd('/');
b = b.TrimEnd('/');
if (a.CompareTo(b) > 0)
MessageBox.Show("Trailing slash removed. Correct: " + a + " > " + b);
else
MessageBox.Show("Trailing slash removed. Not correct: " + a + " <= " + b);
从词汇上讲,“1/2.1/”在“1/2/”之后,没有太多疑问。
这种行为也发生在其他地方,例如使用 Select 方法对数据表进行排序。
我是不是做错了什么?或者这是 .Net 中的错误? 它甚至不应该与文化特定信息等有任何关系,因为斜线是最基本的美国 ASCII 字符集的一部分。
在比较 SQL 服务器 hierarchyID 时,我 运行 喜欢这个。很容易解决,但这是一个有点令人惊讶的问题。
如果我在 C 中的旧技能没有让我失望,我认为 CompareTo 会逐个字符地减去字符的整数值,直到结果不为零。
在前 3 个相同的字符之后,CompareTo 查看第四个字符,这是第一个字符串的点和第二个字符串的斜线。
点字符的整数值为46,斜杠的整数值为47,46-47返回-1,所以"1/2.1/"小于"1/2/"。
Lexically speaking, "1/2.1/" comes after "1/2/", and there is not much question about that.
为什么会在后面呢?在 ASCII chart 上,/
紧跟在 .
之后。
给定以下两个字符串,在到达第 4 个字符之前它们是相等的。然后比较/
和.
,/
更大。所以您看到的结果 (a < b
) 实际上是正确的。
1/2.1/
1/2/
调用 TrimEnd()
后,您最终得到两个不同的字符串,其中和 a > b
.
1/2.1
1/2
如果数字右对齐,您可以比较包含数字的字符串:
01/02.00/
01/02.10/
01/10.00/
如果这不可能,请考虑为您的数字创建一个类型
public class ChapterNumber : IComparable<ChapterNumber>
{
private readonly decimal[] _number;
public ChapterNumber(params decimal[] number)
{
_number = number;
}
public int CompareTo(T obj)
{
var other = obj as ChapterNumber;
if (other == null) {
return +1;
}
int len = Math.Min(_number.Length, other._number.Length);
for (int i = 0; i < len; i++) {
int result = _number[i].CompareTo(other._number[i]);
if (result != 0) {
return result;
}
}
return _number.Length.CompareTo(other._number.Length);
}
public override ToString()
{
return String.Join('/', _number) + "/";
}
}
用法:
var a = new ChapterNumber(1, 2.1m);
var b = new ChapterNumber(1, 2);
if (a.CompareTo(b) > 0) {
...
}