为什么"u1FFF:foo".StartsWith( ":" ) 返回 true?



字符串"u1FFF:foo"u1FFF(或"῿"),对吧?

那么,这两者怎么可能都是真的呢?

"u1FFF:foo".StartsWith(":")       // equals true
"u1FFF:foo".StartsWith("u1FFF")  // equals true
// alternatively, the same:
"῿:foo".StartsWith(":")           // equals true
"῿:foo".StartsWith("῿")          // equals true

.NET是否声称此字符串以两个不同的字符开头?

虽然我觉得非常令人惊讶,并想了解"为什么",但我同样感兴趣的是,我如何强制.NET只按代码点搜索(使用InvariantCulture似乎没有什么作用)?

为了进行比较,下面一个字符,"u1FFE:foo".StartsWith(":")返回false。

一个字符串通常可以被认为以两个不同的字符串开头,这并不奇怪(因为Unicode很复杂)。例如,这些结果几乎总是反映用户想要什么:

"nu0303".StartsWith("u00f1") // true
"nu0303".StartsWith("n")      // false

使用System.Globalization.CharUnicodeInfo.GetUnicodeCategory,可以看到'u1fff'属于"OtherNotAssigned"类别;我不清楚这是否会影响字符串搜索/排序/比较操作(它似乎不会影响规范化,也就是说,字符在规范化后仍然存在)。

如果要进行逐字节比较,请使用StringComparison.Ordinal

因为您使用String.StartsWith()不正确。您应该使用String.StartsWith (String, StringComparison)重载和StringComparison.Ordinal

没有为u1FFF指定任何字符。也就是说,这个代码没有任何语言意义。请参阅希腊语扩展,范围:1F00–1FFF摘录自Unicode标准的字符代码表。MSDN的.NET文档中使用字符串的最佳实践明确指出,如果您需要以忽略自然语言特性的方式比较字符串,则应使用StringComparison.Ordinal:

在方法调用中指定StringComparison.Ordinal或StringComparison_OrdinalIgnoreCase值表示忽略自然语言特征的非语言比较。使用这些StringComparison值调用的方法基于简单字节比较的字符串操作决策,而不是按区域性参数化的大小写表或等价表。在大多数情况下,这种方法最适合字符串的预期解释,同时使代码更快、更可靠。

此外,它建议在这样的方法调用中始终显式指定StringComparison

使用.NET进行开发时,使用字符串时请遵循以下简单建议:

  • 使用重载显式指定字符串操作的字符串比较规则。通常,这涉及到调用具有StringComparison类型参数的方法重载

最新更新