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: