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() 返回意外值的主要内容,如果未能解决你的问题,请参考以下文章
NET问答: 为什么 String.IndexOf 在 .net5 和 netcore3 中返回值不一样?
JavaSE8基础 String indexOf 正向查找 返回字符在字符串中第一次出现时的索引值