String.Compare() != String.Equals() [Josh Free]

System.String contains the static methods ‘Compare’ and ‘Equals’ which are used for string comparison.

public static int Compare(string strA, string strB)

public static bool Equals(string a, string b)

These two methods perform two very different kinds of comparisons.  Developers routinely confuse String.Compare with String.Equals and use the methods interchangeably.  The use of the wrong method can lead to security and globalization issues.

So what’s the difference?  String.Compare performs a culture-sensitive comparison while String.Equals performs an ordinal comparison. Got that?  Well, if the definition of Compare and Equals has you confused then you’re not alone.  Let me try to explain the difference in more detail:

Ordinal Comparison with String.Equals

String.Equals performs an ordinal or binary (e.g., byte for byte) match of the String.  The Equals method is meant to determine exact binary matches of two strings:

Data meaning

Data behavior

Comparison

· Case-sensitive internal identifiers

· Case sensitive identifiers in standards like XML and HTTP

· Case sensitive security-related settings

A non-linguistic identifier, where bytes match exactly.

Ordinal

Culture-Sensitive Comparison with String.Compare

String.Compare performs a culture-sensitive or linguistic evaluation of the String.

The Compare method is meant to determine the sort order of two strings for the current culture.  For example, in Swedish, some vowels with diacritics sort after Z.  However, in other European languages, the same diacritic vowel sorts right after the non-diacritic vowel: 

Data meaning

Data behavior

Comparison

· Data displayed to the user

· Most user input

Data that requires local linguistic customs.

CurrentCulture

Additional Comparison Options with String.Compare(strA, strB, options)

Additional overloads of String.Compare allow developers to specify the exact comparison they want:

public static int Compare(string strA, string strB, StringComparison comparisonType)

It is highly recommended that you use an overload of String.Compare that takes a StringComparison parameter.   Not only do these overloads allow you to define the exact comparison behavior you intended, using them will also make your code more readable for other developers.

Data meaning

Data behavior

Corresponding StringComparsion

Value

· Case-sensitive internal identifiers

· Case sensitive identifiers in standards like XML and HTTP

· Case sensitive security-related settings

A non-linguistic identifier, where bytes match exactly.

Ordinal

· Case-insensitive internal identifiers

· Case-insensitive identifiers in standards like XML and HTTP

· File paths

· Registry keys/values

· Environment variables

· Resource identifiers (handle names, for example)

· Case insensitive security related settings

A non-linguistic identifier, where case is irrelevant, especially a piece of data stored in most Microsoft Windows system services.

OrdinalIgnoreCase

· Some persisted linguistically-relevant data

· Display of linguistic data requiring a fixed sort order

Culturally-agnostic data, which still is linguistically relevant.

InvariantCulture

or

InvariantCultureIgnoreCase

· Data displayed to the user

· Most user input

Data that requires local linguistic customs.

CurrentCulture

or

CurrentCultureIgnoreCase

Further Reading

Finally, for more information on string comparisons please refer to Dave Fetterman’s MSDN technical article New Recommendations for Using Strings in Microsoft .NET 2.0 from May 2005.