为什么“\ u1FFF:foo”.StartsWith(“:”)返回true?

时间:2017-11-09 19:18:47

标签: c# .net f# clr

字符串"\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仅通过代码点进行搜索感兴趣(使用{{1好像什么都没做?)

为了进行比较,下面有一个字符,InvariantCulture返回false。

2 个答案:

答案 0 :(得分:9)

一般来说,一个字符串可能被认为是以两个不同字节相同的字符串开头,这并不奇怪(因为Unicode很复杂)。例如,这些结果几乎总是反映用户的需求:

"n\u0303".StartsWith("\u00f1") // true
"n\u0303".StartsWith("n")      // false

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

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

答案 1 :(得分:1)

因为您错误地使用了String.StartsWith()。您应该使用String.StartsWith (String, StringComparison)重载和StringComparison.Ordinal

没有为\u1FFF分配字符。即此代码没有附加语言含义。有关Unicode标准的字符代码表,请参阅Greek Extended, Range: 1F00–1FFF摘录。来自MSDN的Best Practices for Using Strings in .NET文档明确指出,如果您需要以忽略自然语言功能的方式比较字符串,那么您应该使用StringComparison.Ordinal

  

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

此外,它建议始终在此类方法调用中明确指定StringComparison

  

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

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