What is the difference between StringComparison options, and why do they matter?

C# Strings Intermediate 2–3 Yrs3–5 Yrs Debugging 1 min read

Quick Answer

Ordinal compares by raw char values — fast, deterministic, right for identifiers, keys, file paths, protocol tokens. CurrentCulture/InvariantCulture use linguistic rules — right for sorting text a user sees. Using culture-sensitive comparison for machine data causes subtle bugs (the classic “Turkish i” problem) and is slower.

Ordinal comparison just compares the character codes directly — it's fast and it always does the same thing, so it's what I want for keys, identifiers, file paths, anything machine-oriented. Culture-sensitive comparison applies the linguistic rules of a locale, which is correct for sorting a list of names for a user to read, but wrong and slower for code logic. The famous bug is that in Turkish culture, uppercasing lowercase “i” doesn't give “I”, so a case-insensitive check that relies on the current culture can behave differently on a Turkish machine. So for equality in code I always pass StringComparison.Ordinal or OrdinalIgnoreCase.

  • Prefer string.Equals(a, b, StringComparison.Ordinal) or OrdinalIgnoreCase for equality checks in code.
  • str.ToUpper() / ToLower() for case-insensitive comparison allocates and can be culture-wrong — use OrdinalIgnoreCase instead.
  • Dictionary of strings: pass StringComparer.OrdinalIgnoreCase to the constructor rather than lowercasing keys.
  • Only use culture-aware comparison/sorting when the strings are natural language shown to a person.