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? ThanksAnonymous
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 takeAnonymous
June 13, 2007
Common INFO: · const is "baked" into the assembly. If you have to change the const value inAnonymous
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.aspxAnonymous
June 29, 2007
I recently had an app that I used the VSTS Profiler on to find that a significant portion of time wasAnonymous
May 21, 2008
Research Developer Mahmoud's question was quite reasonable on its face: Hi All, I was having a problem,