Which StringComparison? Ordinal!

I’ve never had to deal with localization, so I haven’t put much thought into the various .NET internationalization features. In the case of StringComparison, I should have done my homework. I’ve seen code samples that use any combination of CurrentCulture, InvariantCulture and Ordinal, but MSDN is very clear: Ordinal and OrdinalIgnoreCase are almost always the right choice. This is especially true for strings like URLs that should never have non-ASCII characters anyway.

The specific MSDN recommendations are worth repeating:

  • DO: Use StringComparison.Ordinal or OrdinalIgnoreCase for comparisons as your safe default for culture-agnostic string matching.
  • DO: Use StringComparison.Ordinal and OrdinalIgnoreCase comparisons for increased speed.
  • DO: Use StringComparison.CurrentCulture-based string operations when displaying the output to the user.
  • DO: Switch current use of string operations based on the invariant culture to use the non-linguistic StringComparison.Ordinal or StringComparison.OrdinalIgnoreCase when the comparison is linguistically irrelevant (symbolic, for example).
  • DO: Use ToUpperInvariant rather than ToLowerInvariant when normalizing strings for comparison.
  • DON’T: Use overloads for string operations that don’t explicitly or implicitly specify the string comparison mechanism.
  • DON’T: Use StringComparison.InvariantCulture-based string operations in most cases; one of the few exceptions would be persisting linguistically meaningful but culturally-agnostic data.

First, note that Ordinal comparisons are significantly faster, “essentially a [byte-wise] C runtime strcmp.”

More importantly, note the recommendation to specify the comparison mechanism whenever possible, as different methods have different default behavior. In BCL 2.0, String.Equals is Ordinal by default, but the majority (Compare, IndexOf, StartsWith, etc) use CurrentCulture. InfoQ recently reported that these defaults will change in .NET 4.0; in fact, the shift has already started with BCL 2.0.5 that shipped with Silverlight 2.0.

For example, in mscorlib, Version=2.0.0.0:

public int IndexOf(string value)
{
    return CultureInfo.CurrentCulture.CompareInfo.IndexOf(this, value);
}

But in Silverlight’s mscorlib, Version=2.0.5.0:

public int IndexOf(string value)
{
    return this.IndexOf(value, StringComparison.Ordinal);
}

So be careful porting string-manipulation code for “linguistically meaningful but culturally-agnostic data,” and other data too, into Silverlight. If you are at all interested in internationalization, the MSDN article is definitely worth a read. And even if you’re not, at least remember to specify StringComparison types.

One Response to “Which StringComparison? Ordinal!”

  1. Leonard Lobel Says:

    Great info, thanks!


Comments are closed.