Sunday, February 18, 2007 7:31 PM
Michael S. Kaplan
When Equals ≠ ==
There are two different ways to talk about equality in C# -- one with the Equals method, the other with the operator ==.
(There is also sometimes a ReferenceEquals method and other times a Compare method one could use looking for a return value of 0, but we'll leave them aside for now)
The question that came in the other day from Bertrand:
We recently had a bug that was caused by a direct == comparison between a CultureInfo instance and CultureInfo.InvariantCulture. == can return false even though the instance is the invariant culture. Using culture.Equals returns the right result consistently and should be used whenever doing culture info comparisons instead of ==.
Behind the scenes, the CultureInfo class does not override the == operator, so it us doing a reference comparison to look whether two objects are referencing one instance rather than two different instances that happen to point to the same object. In many situations the difference can be quite significant in terms of behavior, though in the case of Invariant this is not true since the object cannot be modified. Which perhaps helps to add to the confusion a bit.
And the exact semantic of the CultureInfo.Equals method is simple enough:
- Do the two cultures have the same CultureInfo.Name ?
- Does the CompareInfo.Equals method when pointed at the respective CompareInfo objects of the two cultures return true?
This method has its own two subparts to it:
- Are the two CompareInfo.LCID values the same?
- Do the two CompareInfo objects have the same CompareInfo.Name?
The addition of the CompareInfo stuff happened first in 2.0, in order to support the special GetCultureInfo overload that allows them to be different, added for SQLCLR consistency (which I still haven't talked about, though I will some day, I promise!).
There are some interesting side effects of the implementation:
- == can return false when the two instances are guaranteed to return identical results in all operations (e.g. when both cultures are instances of InvariantCulture);
- Equals can return true when the two instances might return not return results in all operations (e.g. when looking at userOverride==false vs. userOverride=true instances of the same culture).
I guess what is important here is to step back and try and figure out what one is trying to do in checking for equality. That is the only way to make sure one is not surprised by the answer one gets....
This post brought to you by ≠ (U+2260, a.k.a. NOT EQUAL TO)