Difference between InvariantCulture and Ordinal string comparison
在比较C中的两个字符串是否相等时,不变文化和序数比较有什么区别?
不变文化
使用一组"标准"的字符顺序(A、B、C…)等等)。这与某些特定的区域设置不同,这些区域设置可以按不同的顺序对字符进行排序("a-with-acute"可能在"a"之前或之后,具体取决于区域设置,等等)。
依次的另一方面,只查看表示字符的原始字节的值。
http://msdn.microsoft.com/en-us/library/e6883c06.aspx上有一个很好的示例,显示了各种字符串比较值的结果。最后,它显示(节选):
1 2 3 4 5 6 7 8 9 | StringComparison.InvariantCulture: LATIN SMALL LETTER I (U+0069) is less than LATIN SMALL LETTER DOTLESS I (U+0131) LATIN SMALL LETTER I (U+0069) is less than LATIN CAPITAL LETTER I (U+0049) LATIN SMALL LETTER DOTLESS I (U+0131) is greater than LATIN CAPITAL LETTER I (U+0049) StringComparison.Ordinal: LATIN SMALL LETTER I (U+0069) is less than LATIN SMALL LETTER DOTLESS I (U+0131) LATIN SMALL LETTER I (U+0069) is greater than LATIN CAPITAL LETTER I (U+0049) LATIN SMALL LETTER DOTLESS I (U+0131) is greater than LATIN CAPITAL LETTER I (U+0049) |
你可以看到,不变培养产生(U+0069,U+0049,U+00131),序数产生(U+0049,U+0069,U+00131)。
例如,它确实很重要-有一种叫做字符扩展的东西
1 2 3 4 5 | var s1 ="Strasse"; var s2 ="Stra?e"; s1.Equals(s2, StringComparison.Ordinal); //false s1.Equals(s2, StringComparison.InvariantCulture); //true |
和
指向在.NET框架中使用字符串的最佳实践:
- 使用
StringComparison.Ordinal 或StringComparison.OrdinalIgnoreCase 进行比较,作为文化不可知字符串匹配的安全默认值。 - 使用与
StringComparison.Ordinal 或StringComparison.OrdinalIgnoreCase 的比较以获得更好的性能。 - 当比较与语言无关时(例如,符号),使用非语言的
StringComparison.Ordinal 或StringComparison.OrdinalIgnoreCase 值,而不是基于CultureInfo.InvariantCulture 的字符串操作。
最后:
- 在大多数情况下,不要使用基于
StringComparison.InvariantCulture 的字符串操作。少数例外之一是当你坚持有语言意义但文化上不可知的数据。
另一个方便的区别(在英语中重音不常见)是,不变区域性比较首先按不区分大小写比较整个字符串,然后根据需要(和要求)在第一次比较后仅按大小写区分不同的字母。(当然,您也可以进行不区分大小写的比较,这是不区分大小写的。)更正:重音字母被认为是同一个字母的另一种风格,比较字符串时,首先忽略重音,然后在一般字母都匹配的情况下对其进行说明(与不同的大小写不同,但最终不会忽略)。在不区分大小写的比较中)。这组人将相同单词的重音版本放在一起,而不是在第一个重音差异处完全分开。这是通常在字典中可以找到的排序顺序,大写单词出现在它们的小写等价物旁边,重音字母靠近相应的未重音字母。
顺序比较严格地比较数字字符值,在第一个差异处停止。这种排序方式将大写字母与小写字母完全分离(重音字母可能与小写字母分离),因此大写单词的排序方式不会接近小写字母。
InvariantCulture还认为大写字母大于小写字母,而Ordinal认为大写字母小于小写字母(保留了以前计算机使用小写字母之前的ASCII,因此首先分配大写字母,因此其值低于后来添加的小写字母)。
例如,按序数:
按不变文化:
尽管这个问题是关于平等的,为了便于快速的视觉参考,这里的一些字符串的排序使用了几个文化来说明其中的一些特性。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | Ordinal 0 9 A Ab a aB aa ab ss ? ?b ? ? ?b ぁ あ ァ ア 亜 A IgnoreCase 0 9 a A aa ab Ab aB ss ? ? ?b ?b ? ぁ あ ァ ア 亜 A -------------------------------------------------------------------- InvariantCulture 0 9 a A A ? ? aa ab aB Ab ?b ?b ss ? ァ ぁ ア あ 亜 IgnoreCase 0 9 A a A ? ? aa Ab aB ab ?b ?b ? ss ァ ぁ ア あ 亜 -------------------------------------------------------------------- da-DK 0 9 a A A ab aB Ab ss ? ? ? ?b ?b aa ァ ぁ ア あ 亜 IgnoreCase 0 9 A a A Ab aB ab ? ss ? ? ?b ?b aa ァ ぁ ア あ 亜 -------------------------------------------------------------------- de-DE 0 9 a A A ? ? aa ab aB Ab ?b ?b ? ss ァ ぁ ア あ 亜 IgnoreCase 0 9 A a A ? ? aa Ab aB ab ?b ?b ss ? ァ ぁ ア あ 亜 -------------------------------------------------------------------- en-US 0 9 a A A ? ? aa ab aB Ab ?b ?b ? ss ァ ぁ ア あ 亜 IgnoreCase 0 9 A a A ? ? aa Ab aB ab ?b ?b ss ? ァ ぁ ア あ 亜 -------------------------------------------------------------------- ja-JP 0 9 a A A ? ? aa ab aB Ab ?b ?b ? ss ァ ぁ ア あ 亜 IgnoreCase 0 9 A a A ? ? aa Ab aB ab ?b ?b ss ? ァ ぁ ア あ 亜 |
观察:
de-DE 、ja-JP 和en-US 的排序方式相同。Invariant 只对ss 和? 进行分类,不同于上述三种文化。da-DK 的分类非常不同- 所有样本培养的
IgnoreCase 标志物
用于生成上表的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | var l = new List<string> {"0","9","A","Ab","a","aB","aa","ab","ss","?", "?","?b","?","?b","あ","ぁ","ア","ァ","A","亜" }; foreach (var comparer in new[] { StringComparer.Ordinal, StringComparer.OrdinalIgnoreCase, StringComparer.InvariantCulture, StringComparer.InvariantCultureIgnoreCase, StringComparer.Create(new CultureInfo("da-DK"), false), StringComparer.Create(new CultureInfo("da-DK"), true), StringComparer.Create(new CultureInfo("de-DE"), false), StringComparer.Create(new CultureInfo("de-DE"), true), StringComparer.Create(new CultureInfo("en-US"), false), StringComparer.Create(new CultureInfo("en-US"), true), StringComparer.Create(new CultureInfo("ja-JP"), false), StringComparer.Create(new CultureInfo("ja-JP"), true), }) { l.Sort(comparer); Console.WriteLine(string.Join("", l)); } |
不变量是一种语言上合适的比较类型。
序数是一种二进制比较类型。(快)< BR>见http://www.siao2.com/2004/12/29/344136.aspx
下面是一个示例,其中使用InvariantCultureIgnoreCase和OrdinalIgnoreCase进行的字符串相等性比较不会得出相同的结果:
1 2 3 4 5 6 7 | string str ="\xC4"; //A with umlaut, ? string A = str.Normalize(NormalizationForm.FormC); //Length is 1, this will contain the single A with umlaut character (?) string B = str.Normalize(NormalizationForm.FormD); //Length is 2, this will contain an uppercase A followed by an umlaut combining character bool equals1 = A.Equals(B, StringComparison.OrdinalIgnoreCase); bool equals2 = A.Equals(B, StringComparison.InvariantCultureIgnoreCase); |
如果运行此函数,equals1将为false,equals2将为true。
不需要使用花哨的Unicode字符Exmaples来显示差异。这是我今天发现的一个简单的例子,它令人惊讶,只包含ASCII字符。
根据ASCII表,当按顺序比较时,
1 2 3 4 | PS> [System.StringComparer]::Ordinal.Compare("_","0") 47 PS> [System.StringComparer]::InvariantCulture.Compare("_","0") -1 |
始终尝试在接受它为重载的字符串方法中使用InvariantCulture。通过使用不变的区域性,您是安全的。许多.NET程序员可能不使用此功能,但如果您的软件将由不同的区域性使用,则InvariantCulture是一个非常方便的功能。