C# string.IndexOf() 返回意外值

Posted

技术标签:

【中文标题】C# string.IndexOf() 返回意外值【英文标题】:C# string.IndexOf() returns unexpected value 【发布时间】:2013-06-26 03:49:44 【问题描述】:

此问题适用于 C#、.net Compact Framework 2 和 Windows CE 5 设备。

我在 .net DLL 中遇到了一个错误,该错误多年来一直在非常不同的 CE 设备上使用,但没有显示任何问题。突然,在新的 Windows CE 5.0 设备上,这个 bug 出现在以下代码中:

string s = "Print revenue receipt"; // has only single space chars 
int i = s.IndexOf("  "); // two space chars

我希望 i 为 -1,但直到今天才如此,当时 indexOf 突然返回 5。

由于使用时不会发生这种行为

int i = s.IndexOf("  ", StringComparison.Ordinal);

,我很确定这是一种基于文化的现象,但我无法识别这种新设备的不同之处。它是已知设备的大致相同版本(只是更快的 cpu 和新板)。

两个设备:

运行具有相同本地化的 Windows CE 5.0 System.Environment.Version 报告“2.0.7045.0” CultureInfo.CurrentUICulture 和 CultureInfo.CurrentCulture 报告“en-GB”(也使用“de-DE”进行测试) “所有”相关的注册表项都是相等的。

新设备预装了 CF 3.5,我实验性地重命名了它的 GAC 文件,描述的行为没有改变。由于在运行时总是报告版本 2.0.7045.0,我假设这些程序集没有任何效果。

虽然这不难解决,但当事情看起来如此神奇时,我无法忍受。任何提示我错过了什么?

编辑:越来越陌生,看截图:

还有一个:

【问题讨论】:

你运行这个 exact 代码,你得到 5? 当然不完全是,请看我上面的截图。我也纠正了这个问题。有趣的点:* s = "打印收入"; // 结果 -1 * s = "Drucke Beleg aus"; // 结果 -1 (!) 请原谅我的频繁编辑,我是 SO 新手。 i.stack.imgur.com/iGxNb.png 您是否尝试循环遍历s 字符串中的每个字符以查看它们是否是我们看不到显示的任何字符?例如,在这个问题***.com/questions/4893216/… 中,它是一个软连字符,导致您遇到的问题相同 @ErgibtSinn 您是否尝试过清理和重建您的项目? 【参考方案1】:

我相信您已经使用序数搜索得到了答案

    int i = s.IndexOf("  ", StringComparison.Ordinal);

您可以阅读String Class 文档中的一小部分,其中有关于该主题的内容:

字符串搜索方法,例如 String.StartsWith 和 String.IndexOf,也可以执行文化敏感或序号字符串比较。下面的示例说明了使用 IndexOf 方法进行序号比较和区分区域性的比较之间的差异。当前文化为英语(美国)的文化敏感搜索将子字符串“oe”视为与连字“œ”匹配。由于软连字符 (U+00AD) 是零宽度字符,因此搜索会将软连字符视为等效于 Empty,并在字符串的开头找到匹配项。另一方面,序数搜索在任何一种情况下都找不到匹配项。

【讨论】:

我知道这是对“我该如何解决这个问题?”这个问题的正确答案。 - 但我的问题是:“为什么会这样?”。 要找出答案,我建议您在调试中迭代处理问题字符串的每个字符。里面可能有你没看到的角色 这无法解释为什么它适用于所有其他设备。至少 VS 调试器在复制+粘贴到十六进制编辑器时不提供任何隐藏字符。请注意字母表上带有循环的示例。【参考方案2】:

文化的东西在某些系统上看起来真的很神奇。经过多年的痛苦,我总是做总是手动将文化信息设置为InvariantCulture,我并不明确希望不同文化有不同的行为。所以我的建议是:让IndexOf 检查始终使用相同的文化信息,如下所示:

int i = s.IndexOf("  ", StringComparison.InvariantCulture);

【讨论】:

我也试过了,但出现了同样的行为。只有 StringComparison.Ordinal 修复了它。我需要在周末开始之​​前知道关键区别隐藏在哪里;-) 这似乎也很难理解,为什么两个空格可以被视为等于一个,而 string.Equals(" "," ");(两个空格对一个空格)返回 false。 .. String.Equals 使用序数比较;试试String.Compare(" ", " ") String.Compare 返回 1,因此它们不被识别为相等。【参考方案3】:

http://msdn.microsoft.com/en-us/library/k8b1470s.aspx 的引用说明:

"字符集包含可忽略字符,即在执行语言或文化敏感比较时不考虑的字符。在文化敏感搜索中,如果 value 包含可忽略字符,则结果等同于使用该字符进行搜索删除。”

这是来自 4.5 的参考,以前版本的参考不包含类似的内容。

所以让我猜一下:他们已将规则从 4.0 更改为 4.5,现在双空格序列的第二个空格被认为是“可忽略字符” - 至少如果引擎将您的字符串识别为英文文本(如您的示例字符串 s),否则不是。

不知何故,在您的新设备上,使用了 4.5 dll 而不是预期的 2.0 dll。

一个疯狂的猜测,我知道:)

【讨论】:

一个非常疯狂的猜测,但合理且受过教育。 System.Environment.Version 在运行时显示 2.0.7045.0,因此使用 CF2 SP2。除了这个 CF2 安装之外,还有 CF3.5 DLL。

以上是关于C# string.IndexOf() 返回意外值的主要内容,如果未能解决你的问题,请参考以下文章

比较绕的indexof()

NET问答: 为什么 String.IndexOf 在 .net5 和 netcore3 中返回值不一样?

JavaSE8基础 String indexOf 正向查找 返回字符在字符串中第一次出现时的索引值

SQL Server 存储过程返回意外值

ASCIIEncoding.ASCII.GetBytes() 返回意外值

String的indexOf方法