Share via


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.

Comments

  • Anonymous
    May 31, 2007
    Hello. Surely the confusion is over the default behavior of Equals vs Compare. Both methods provide overloads that take a StringComparison, so both can do ordinal or cultural comparisons. The real difference is that Compare will tell you whether one string is less than or greater than another, whereas Equals will only tell you whether they are equal. Oh, and the default behavior of == is the same as Equals, right? Thanks

  • Anonymous
    May 31, 2007
    If you are someone who reads the BCL Team blog, you may have seen Josh Free's String.Compare() != String.Equals()

  • Anonymous
    June 01, 2007
    Hi Kent, Yes, == is the same as the default Equals overload (Ordinal).

  • Anonymous
    June 01, 2007
    This is a nice, clear explanation. You should have the user education folks copy at least a little of this into the method summary on the VS documentation page for the String.Compare Method topic. It currently reads "Compares two specified String objects.", which is perfectly correct, but not terribly helpful. Sort of like that old MSFT joke about the guy in the helicopter. That topic could also use a See Also link to the "Performing Culture-Insensitive String Comparisons" and "String.Equals Method" topics.

  • Anonymous
    June 05, 2007
    Of course, to confuse matters even more, String.Equals returns a boolean, while String.Compare returns an int. And, if you cast the return from String.Compare to a boolean, it will be the exact OPPOSITE of calling String.Equals with the same paramters.

  • Anonymous
    June 13, 2007
    Last update: June 13 , 2007 Document version 0.6 Preface If you have something to add, or want to take

  • Anonymous
    June 13, 2007
    Common INFO: · const is "baked" into the assembly. If you have to change the const value in

  • Anonymous
    June 13, 2007
    This section describes the common .NET tips which don't relates to the specific category. INFO:

  • Anonymous
    June 20, 2007
    Thanks.  But what about ==?  Does that call .Equals()? .Compare()?  Something else?

  • Anonymous
    June 20, 2007
    == is just like String.Equals as you can see in here: http://msdn2.microsoft.com/en-us/library/system.string.op_equality.aspx

  • Anonymous
    June 29, 2007
    I recently had an app that I used the VSTS Profiler on to find that a significant portion of time was

  • Anonymous
    May 21, 2008
    Research Developer Mahmoud's question was quite reasonable on its face: Hi All, I was having a problem,