InvariantCulture和Ordinal字符串比较之间的区别

时间:2009-01-29 18:21:45

标签: c# .net string-comparison ordinal

当比较c#中的两个字符串是否相等时,InvariantCulture和Ordinal比较之间的区别是什么?

9 个答案:

答案 0 :(得分:272)

InvariantCulture的

使用“标准”字符排序集(a,b,c,...等)。这与某些特定区域设置形成对比,这些区域设置可能按不同顺序对字符进行排序('a-with-acute'可能在 之前或 之后'a',具体取决于区域设置,等等。)

另一方面,看起来纯粹是表示字符的原始字节的值。


http://msdn.microsoft.com/en-us/library/e6883c06.aspx处有一个很好的示例,它显示了各种StringComparison值的结果。一直到最后,它显示(摘录):

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)

你可以看到InvariantCulture收益率(U + 0069,U + 0049,U + 00131),序数收益率(U + 0049,U + 0069,U + 00131)。

答案 1 :(得分:208)

重要的是,例如 - 有一种叫做角色扩展的东西

var s1 = "Strasse";
var s2 = "Straße";

s1.Equals(s2, StringComparison.Ordinal);           //false
s1.Equals(s2, StringComparison.InvariantCulture);  //true

使用InvariantCulture,ß字符会扩展为ss。

答案 2 :(得分:85)

指向Best Practices for Using Strings in the .NET Framework

  • 使用StringComparison.OrdinalStringComparison.OrdinalIgnoreCase进行比较,作为与文化无关的字符串匹配的安全默认值。
  • 使用与StringComparison.OrdinalStringComparison.OrdinalIgnoreCase的比较可获得更好的效果。
  • 当比较在语言上无关时(例如,符号),请使用非语言StringComparison.OrdinalStringComparison.OrdinalIgnoreCase值而不是基于CultureInfo.InvariantCulture的字符串操作。

最后:

  • 在大多数情况下,不要使用基于StringComparison.InvariantCulture的字符串操作。少数例外情况之一是当你坚持语言上有意义但文化上不可知的数据时。

答案 3 :(得分:55)

另一个方便的区别(在英语中,重音非常见)是InvariantCulture比较首先按不区分大小写比较整个字符串,然后在必要时(和请求)在首先仅对不同的字母进行比较后进行区分。 (当然,您也可以进行不区分大小写的比较,但不会区别于案例。)更正:重音字母被认为是相同字母的另一种字母,首先比较字符串如果一般字母全部匹配,则忽略重音然后对其进行计算(与不同情况一样,除非在不区分大小写的比较中最终忽略)。这将其他相同单词的重音版本组合在一起,而不是在第一个重音差异处完全分开。这是您通常在字典中找到的排序顺序,大写单词出现在它们的小写等价物旁边,重音字母靠近相应的非重音字母。

序数比较严格比较数字字符值,停在第一个差异处。这种大写字母与小写字母(以及可能与这些字母分开的重音字母)完全分开,因此大写单词在其小写等价物附近无法排序。

InvariantCulture还认为大写字母大于小写字母,而Ordinal认为大写字母小于小写字母(从计算机使用小写字母之前的旧日期中保留ASCII,大写字母首先分配,因此值低于后面添加了小写字母。)

例如,通过Ordinal:"0" < "9" < "A" < "Ab" < "Z" < "a" < "aB" < "ab" < "z" < "Á" < "Áb" < "á" < "áb"

通过InvariantCulture:"0" < "9" < "a" < "A" < "á" < "Á" < "ab" < "aB" < "Ab" < "áb" < "Áb" < "z" < "Z"

答案 4 :(得分:28)

虽然问题是关于 equality ,但是为了快速直观引用,这里使用一些文化说明一些字符串排序的顺序,这些文化说明了那里的一些特性。 / p>

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-DEja-JPen-US按照相同的方式排序
  • Invariant只对ssß进行排序,与上述三种文化不同
  • da-DK排序方式完全不同
  • IgnoreCase标志对所有抽样文化都很重要

用于生成上表的代码:

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));
}

答案 5 :(得分:26)

不变性是一种语言上恰当的比较类型 序数是二元类型的比较。 (快)
http://www.siao2.com/2004/12/29/344136.aspx

答案 6 :(得分:5)

以下是使用InvariantCultureIgnoreCase和OrdinalIgnoreCase进行字符串相等性比较时不会产生相同结果的示例:

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。

答案 7 :(得分:2)

无需使用花哨的unicode char exmaples来显示差异。这是我今天发现的一个简单的例子,它令人惊讶,仅由ASCII字符组成。

根据ASCII表,0(0x48)在通常比较时小于_(0x95)。 InvariantCulture会说相反的话(下面的PowerShell代码):

PS> [System.StringComparer]::Ordinal.Compare("_", "0")
47
PS> [System.StringComparer]::InvariantCulture.Compare("_", "0")
-1

答案 8 :(得分:-7)

始终尝试在那些接受它作为重载的字符串方法中使用InvariantCulture。通过使用InvariantCulture,您可以放心使用。许多.NET程序员可能不会使用此功能,但如果您的软件将被不同的文化使用,InvariantCulture是一个非常方便的功能。