不区分大小写的字符串比较奇怪的行为

Che*_*hen 6 .net c# java unicode

这种情况发生在C#和Java中,所以我认为这不是一个bug,只是想知道为什么.

var s = "";
var lower = s.ToLower();
var upper = s.ToUpper();

if (!lower.Equals(upper, StringComparison.OrdinalIgnoreCase))
{
    //How can this happen?
}
Run Code Online (Sandbox Code Playgroud)

根据这个页面,""的小写是"",与IgnoreCase选项相比,它们应该相等.为什么他们不平等?

And*_*kin 1

为了捍卫 Java API:该方法的文档String.equalsIgnoreCase从未声称它可以在任意 Unicode 代码点上“按预期”工作。它说:

如果以下至少一项为真,则两个字符 c1 和 c2 被视为相同,忽略大小写:

  • 两个字符相同(通过 == 运算符进行比较)
  • 将方法 Character.toUpperCase(char) 应用于每个字符会产生相同的结果
  • 将方法 Character.toLowerCase(char) 应用于每个字符会产生相同的结果

因此,文档非常明确地指出它适用Character.toUpperCasechars,即 UTF-16代码单元,而不是 Unicode 代码点。

Character.toUpperCase(int codePoint)如果您在每个代码上使用该方法,则比较的行为将按预期进行。这是 Scala 中的一个简短示例(使用完全相同的 Java API,高阶forall方法希望是不言自明的):

val a = ""
val b = ""
(a.codePoints.toArray zip b.codePoints.toArray).forall { 
  case (x, y) => 
  Character.toLowerCase(x) == Character.toLowerCase(y) 
}
Run Code Online (Sandbox Code Playgroud)

印刷

true
Run Code Online (Sandbox Code Playgroud)

正如预期的那样。这是为什么呢?我认为人们可以放心地将这一问题归咎于向后兼容性。