为什么字符串.StartsWith("\u2D2D")总是返回true?

25

我在 C# 中尝试解析字符串,并发现对于我尝试的每个字符串,string.StartsWith("\u2D2D") 都会返回 true。为什么会这样?

似乎它适用于每个字符。我在 .Net 4.5 中尝试了这段代码,调试器没有停止。

for (char i = char.MinValue; i < char.MaxValue; i++)
{
    if(!i.ToString().StartsWith("\u2d2d"))
    {
        Debugger.Break();
    }
}

这是一行代码用于检查一堆东西。对于我来说返回falseEnumerable.Range(0, 10000).Any(x => !((char)x).ToString().StartsWith("\u2D2D")) - DLeh
这一定是因为所有的字符串都是格鲁吉亚语:D - Alex
@Caramiriel 可能是这样,但 U+2D2D 应该只有一个长度 - CodeCaster
2
可能查看String.StartsWith的参考源代码会很有用,链接在这里:http://referencesource.microsoft.com/#mscorlib/system/string.cs,8281103e6f23cb5c - Asad Saeeduddin
1
U+2D2D是在Unicode版本6.1中添加的,似乎6.1的所有4个长度字符都有相同的问题。从一些快速测试来看,这似乎适用于所有大于6.0版本。 - redrobot
显示剩余6条评论
1个回答

16

我想我会试一试。

据我所知,U+2D2D是在Unicode v6.1中添加的(来源 / 来源)。

.NET框架或本地调用支持较低版本:

字符串比较中使用的区域性敏感排序和大小写规则取决于.NET Framework的版本。 在运行Windows 8操作系统上的.NET Framework 4.5中,排序、大小写处理、规范化和Unicode字符信息符合Unicode 6.0标准。 在其他操作系统上,它符合Unicode 5.0标准。(来源

因此需要将其标记为可忽略字符,就好像该字符根本不存在一样。

字符集包括可忽略字符,这些字符在执行语言学或区域性敏感比较时不予考虑。(来源

例如:

var culture = new CultureInfo("en-US");
int result = culture.CompareInfo.Compare("", "\u2D2D", CompareOptions.None);
Assert.AreEqual(0, result);

string.StartsWith 使用类似的实现,但使用 CompareInfo.IsPrefix(string, string, CompareOptions) 代替。


这个比其他答案更有意义,点赞。 - Der Kommissar
我刚刚测试了一个空字符串值与.StartsWith(),并且它返回真。也就是说,"abc".StartsWith("")true。这很有道理,因为它基本上是在说底层的字符串起始于至少一个空字符串。当底层的Kernel32.dll方法FindNLSStringEx看到它认为无效的值时,它会简单地将它们删除(或者其他一些更低级别的方法会)。结果是当运行string.StartsWith("")时,它返回真。 - Der Kommissar
@stakx:谢谢,但我不介意。我只是想知道为什么会发生这种情况,也许下次我自己遇到类似的问题时会有所帮助。 :) - Caramiriel
@EBrown:在空前缀("")的情况下,实际上并不会调用FindNLSStringEx。0长度前缀的特殊情况由.NET处理。此外,根据这个答案,这是anyString.StartsWith("\u2D2D")返回true的逻辑原因。 - stakx - no longer contributing
我刚刚测试了一个空字符串值的.StartsWith()方法,它返回true。这是定义好的(也是合乎逻辑的)结果。如果字符串长度==0,它就会这样做。 - TaW

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接