54

我正在从配置文件中读取加密的凭据/连接字符串。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”位真的明智吗?

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

4

3 回答 3

66

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

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

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

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

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

这些新建议和 API 的存在是为了减轻对默认字符串 API 行为的错误假设。在语言上解释非语言字符串数据时出现的错误的典型示例是“Turkish-I”问题。

对于几乎所有拉丁字母,包括美国英语,字符 i (\u0069) 是字符 I (\u0049) 的小写版本。这种大小写规则很快成为在这种文化中编程的人的默认设置。然而,在土耳其语(“tr-TR”)中,存在一个大写的“i with a dot”字符(\u0130),它是 i 的大写版本。同样,在土耳其语中,有一个小写“i without a dot”或 (\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
于 2012-06-08T00:03:36.390 回答
27

CA1309: UseOrdinalStringComparison

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


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

使用序号排序规则的操作基于字符串中每个 Char 的数值(Unicode 代码点)执行比较。序数比较速度很快,但对文化不敏感。当您使用序数排序规则对以 Unicode 字符 (U+) 开头的字符串进行排序时,如果 xxxx 的数值小于 yyyy,则字符串 U+xxxx 位于字符串 U+yyyy 之前。

而且,正如您所说...您正在阅读的字符串值对文化不敏感,因此使用 Ordinal 比较而不是 Word 比较是有意义的。请记住,Ordinal 的意思是“这不是文化敏感的”。

于 2012-06-07T23:51:08.740 回答
7

回答您的具体问题:不,但是静态分析工具无法意识到您的输入值永远不会包含特定于语言环境的信息。

于 2012-06-07T23:55:10.363 回答