使用 .NET 6(使用 ICU 库进行字符串比较)时,以下 C# 代码返回 false:
Thread.CurrentThread.CurrentCulture = new CultureInfo("de-de");
Thread.CurrentThread.CurrentUICulture = new CultureInfo("de-de");
"ß".Equals("SS", StringComparison.CurrentCultureIgnoreCase); // false with ICU
根据我的理解,根据 Unicode 大小写折叠规则(以及 - 更重要的是 - 标准德语拼写规则),这应该是正确的:
00DF; F; 0073 0073; # LATIN SMALL LETTER SHARP S
(CaseFolding.txt)
使用旧版 Microsoft NLS 实现时,上述代码返回 true。
那么为什么 .NET 6 使用的 ICU 库与 Unicode 标准不同,或者我对标准的理解不正确?
Unicode 很复杂。
事实证明这种行为是故意的。有关 tarekgh 总结问题的问题,请参阅 this Github 问题:
ICU 整理工作使用所谓的整理强度。 强度可以是一级、二级、三级或四级。我们是 尝试将 .NET 比较选项尽可能多地映射到其中之一 这些力量。除了这种特殊情况之外,它工作得很好。 不幸的是,如果有 ICU 实力,ICU 使 ß 仅等于 ss 是主要的。我们无法在 .NET 中默认切换到该强度 因为会破坏很多其他东西。
此问题的解决方法是使用
StringComparer.Create(CultureInfo.CurrentCulture, CompareOptions.IgnoreNonSpace | CompareOptions.IgnoreCase)
- CompareOptions.IgnoreNonSpace
强制主要排序强度,在这种情况下 ß
和 ss
将比较相等。
这种切换可能会产生一些意想不到的副作用,但至少说德语的人会很高兴。