Skip to content

Instantly share code, notes, and snippets.

@congyiwu
Last active January 21, 2021 00:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save congyiwu/f9f02435ffb344f09ab69f6270e2a99c to your computer and use it in GitHub Desktop.
Save congyiwu/f9f02435ffb344f09ab69f6270e2a99c to your computer and use it in GitHub Desktop.
Ordinal vs. InvariantCulture

In .NET, when should you use Ordinal(IgnoreCase) vs InvariantCulture(IgnoreCase)?

Ordinal(IgnoreCase) does simple byte comparisions, similar to memcmp, and is faster.

InvariantCulture(IgnoreCase) applies extra linguistic rules that are English-biased, but not guaranteed to exactly match any "real" culture.

Use Ordinal(IgnoreCase) when strings are mostly non-linguistic or opaque, e.g. file names, serial numbers.

  • Note that most filesystems behave closer to Ordinal(IgnoreCase), whereas UIs like File Explorer may re-sort filenames culture-sensitively.

Use InvariantCulture(IgnoreCase) when:

  • Strings have linguistic meaning, e.g. people's names, words that you'd expect look up in a dictionary (the kind with definitions for people as opposed to a hashset).
  • And it is impractical to pick a specific culture (Otherwise, you should the more specific CultureInfo)
// The examples below are w/ .NET Framework in LINQPad 5, where String.Equals("ss", "ß", StringComparison.InvariantCultureIgnoreCase) == true
// In .NET Core in LINQPad 6, it's now *false*, which is craaaazy!

// Non-linguistic string example.
// OrdinalIgnoreCase would be preferred if these were serial numbers.
String.Equals("rrw3rssr0", "rrw3rßr0", StringComparison.InvariantCultureIgnoreCase).Dump(); // true
String.Equals("rrw3rssr0", "rrw3rßr0", StringComparison.OrdinalIgnoreCase).Dump(); // false

// Linguistic string example.
// InvariantCultureIgnoreCase would be preferred if these were addresses around the world.
String.Equals("Kendlerstrasse 1, 5020 Salzburg, Austria", "Kendlerstraße 1, 5020 Salzburg, Austria", StringComparison.InvariantCultureIgnoreCase).Dump(); // true
String.Equals("Kendlerstrasse 1, 5020 Salzburg, Austria", "Kendlerstraße 1, 5020 Salzburg, Austria", StringComparison.OrdinalIgnoreCase).Dump(); // false

// Example with Unicode combining character sequences
string singleCodePoint = "\u00E1";
singleCodePoint.Dump(); // "á"
string combiningCharacterSequence = "a\u0301";
combiningCharacterSequence.Dump(); // "á"
String.Equals(singleCodePoint, combiningCharacterSequence, StringComparison.InvariantCultureIgnoreCase).Dump(); // true
String.Equals(singleCodePoint, combiningCharacterSequence, StringComparison.OrdinalIgnoreCase).Dump(); // false

Official docs:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment