当字符串保证不会更改时,字符串比较是否真的会因区域性而异

本文关键字:字符串 是否 真的 区域性 比较 | 更新日期: 2023-09-27 18:36:42

我正在从配置文件中读取加密的凭据/连接字符串。Resharper告诉我,"String.IndexOf(string)在这里是特定于文化的",在這行:

if (line.Contains("host=")) {
    _host = line.Substring(line.IndexOf(
        "host=") + "host=".Length, line.Length - "host=".Length);

。所以想把它改成:

if (line.Contains("host=")) {
    _host = line.Substring(line.IndexOf("host=", System.StringComparison.Ordinal) + "host=".Length, line.Length -   "host=".Length);

我正在读取的值将始终为"host=",无论应用程序部署在何处。添加这个"System.StringComparison.Ordinal"位真的明智吗?

更重要的是,它会伤害任何东西(使用它)吗?

当字符串保证不会更改时,字符串比较是否真的会因区域性而异

当然。 根据 MSDN (http://msdn.microsoft.com/en-us/library/d93tkzah.aspx),

此方法执行一个单词(区分大小写和区分区域性) 使用当前区域性进行搜索。

因此,如果在不同的区域性下运行它(通过控制面板中的区域和语言设置),则可能会获得不同的结果。

这种特殊情况下,您可能不会有问题,但是在搜索字符串中抛出一个i并在土耳其运行它,它可能会毁了您的一天。

请参阅 MSDN: http://msdn.microsoft.com/en-us/library/ms973919.aspx

这些新的建议和 API 旨在缓解有关默认字符串 API 行为的误导性假设。规范 在非语言字符串数据所在的位置出现错误的示例 语言上的解释是"土耳其语-I"问题。

对于几乎所有拉丁字母,包括美国英语,字符 i (''u0069) 是字符 I (''u0049) 的小写版本。这 大小写规则很快成为某人编程的默认规则 这样的文化。但是,在土耳其语("tr-TR")中,存在一个大写字母 "I with a dot"字符 (''u0130),这是 我。同样,在土耳其语中,有一个小写的"i 没有点",或者 (''u0131),大写为 I。这种行为发生在阿塞拜疆 文化("az")也是如此。

因此,通常做出的关于大写 i 或 小写 I 在所有文化中都无效。如果默认 使用字符串比较例程的重载,它们将是 受文化差异的影响。对于非语言数据,如 以下示例,这可能会产生意外结果:

    Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US")
Console.WriteLine("Culture = {0}",
   Thread.CurrentThread.CurrentCulture.DisplayName);
Console.WriteLine("(file == FILE) = {0}", 
   (String.Compare("file", "FILE", true) == 0));
Thread.CurrentThread.CurrentCulture = new CultureInfo("tr-TR");
Console.WriteLine("Culture = {0}",
   Thread.CurrentThread.CurrentCulture.DisplayName);
Console.WriteLine("(file == FILE) = {0}", 
   (String.Compare("file", "FILE", true) == 0));

由于I的比较不同,结果 更改线程区域性时,比较会更改。这是 输出:

Culture = English (United States)
(file == FILE) = True
Culture = Turkish (Turkey)
(file == FILE) = False

下面是一个没有大小写的示例:

var s1 = "é"; //é as one character (ALT+0233)
var s2 = "é"; //'e', plus combining acute accent U+301 (two characters)
Console.WriteLine(s1.IndexOf(s2, StringComparison.Ordinal)); //-1
Console.WriteLine(s1.IndexOf(s2, StringComparison.InvariantCulture)); //0
Console.WriteLine(s1.IndexOf(s2, StringComparison.CurrentCulture)); //0

> CA1309: 使用序号字符串比较

不使用它并没有什么坏处,但是"通过将参数显式设置为 StringComparison.Ordinal 或 StringComparison.OrdinalIgnoreCase,您的代码通常会提高速度,提高正确性,并变得更加可靠。


序数到底是什么,为什么它对你的情况很重要?

使用序号排序规则的操作执行基于比较 字符串中每个字符的数值(Unicode 代码点)。 序号比较速度很快,但不区分区域性。当您使用 序号排序规则,用于对以 Unicode 字符开头的字符串进行排序 (U+),如果值为 xxxx 在数字上小于 yyyy。

而且,正如你所说...您正在读取的字符串值不区分区域性,因此使用序号比较而不是 Word 比较是有意义的。请记住,序号的意思是"这不是文化敏感的"。

要回答您的特定问题:否,但静态分析工具无法意识到您的输入值永远不会包含特定于区域设置的信息。