The difference between InvariantCulture and Ordinal string comparison

Compare whether two strings in c are equal. What's the difference between the InvariantCulture and original comparison?

#1 building

For example, it's really important - there's something called role extension

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

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

With InvariantCulture, the role is extended to ss.

#2 building

point Best practices for using strings in the. NET Framework :

  • Use StringComparison.Ordinal or StringComparison.OrdinalIgnoreCase to compare as a safe default for culture independent string matching.
  • Use to compare with StringComparison.Ordinal or StringComparison.OrdinalIgnoreCase for better performance.
  • When the comparison is language independent (for example, symbols), use a non language StringComparison.Ordinal or StringComparison.OrdinalIgnoreCase value instead of a string operation based on CultureInfo.InvariantCulture.

Last:

  • In most cases, do not use string operations based on StringComparison.InvariantCulture. One of the few exceptions is when you stick to data that is linguistically meaningful but culturally agnostic.

#3 building

Although the problem is about equality, for quick visual reference, here we use some cultural ordering of some strings to illustrate some of the characteristics there.

Ordinal          0 9 A Ab a aB aa ab ss Ä Äb ß ä äb ぁ あ ァ ア A kind of A
IgnoreCase       0 9 a A aa ab Ab aB ss ä Ä äb Äb ß ぁ あ ァ ア A kind of A
--------------------------------------------------------------------
InvariantCulture 0 9 a A A ä Ä aa ab aB Ab äb Äb ss ß ァ ぁ ア あ A kind of
IgnoreCase       0 9 A a A Ä ä aa Ab aB ab Äb äb ß ss ァ ぁ ア あ A kind of
--------------------------------------------------------------------
da-DK            0 9 a A A ab aB Ab ss ß ä Ä äb Äb aa ァ ぁ ア あ A kind of
IgnoreCase       0 9 A a A Ab aB ab ß ss Ä ä Äb äb aa ァ ぁ ア あ A kind of
--------------------------------------------------------------------
de-DE            0 9 a A A ä Ä aa ab aB Ab äb Äb ß ss ァ ぁ ア あ A kind of
IgnoreCase       0 9 A a A Ä ä aa Ab aB ab Äb äb ss ß ァ ぁ ア あ A kind of
--------------------------------------------------------------------
en-US            0 9 a A A ä Ä aa ab aB Ab äb Äb ß ss ァ ぁ ア あ A kind of
IgnoreCase       0 9 A a A Ä ä aa Ab aB ab Äb äb ss ß ァ ぁ ア あ A kind of
--------------------------------------------------------------------
ja-JP            0 9 a A A ä Ä aa ab aB Ab äb Äb ß ss ァ ぁ ア あ A kind of
IgnoreCase       0 9 A a A Ä ä aa Ab aB ab Äb äb ss ß ァ ぁ ア あ A kind of

Observation:

  • De De, JA JP and en US are sorted in the same way
  • Different from the above three cultures, Invariant only ranks ss and di
  • Da DK is totally different
  • The IgnoreCase logo is important for all sampling cultures

Code used to generate the above table:

var l = new List<string>
    { "0", "9", "A", "Ab", "a", "aB", "aa", "ab", "ss", "ß",
      "Ä", "Äb", "ä", "äb", "あ", "ぁ", "ア", "ァ", "A", "A kind of" };

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

#4 building

Invariants are an appropriate type of comparison in language.
Ordinals are binary comparisons. (hurry up)
see http://www.siao2.com/2004/12/29/344136.aspx

#5 building

The following is an example where string equality comparison using invariantresultignorecase and OrdinalIgnoreCase does not give the same result:

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

If you run it, equals1 will be false and equals2 will be true.

Added by elToro on Wed, 15 Jan 2020 12:08:40 +0200