-
Notifications
You must be signed in to change notification settings - Fork 5.2k
Description
Another report on Developer community: https://developercommunity.visualstudio.com/content/problem/430327/stringcomparers-may-return-different-hashcodes-for.html
Docs on string class state that:
Null characters are ignored when performing culture-sensitive comparisons between two strings, including comparisons using the invariant culture.
Also, docs on IEqualityComparer interface state that: Implementations are required to ensure that if the Equals(T, T) method returns true for two objects x and y, then the value returned by the GetHashCode(T) method for x must equal the value returned for y.
However, for all the StringComparers GetHashCode methods (except Ordinal/OrdinalInvariantCase, which it should take null characters into account) they do not consider the fact that if a string only consists of null characters \u0000 it should be treated as if it were string.Empty.
For example, calling StringComparer.InvariantCulture.Equals method with string.Empty and new string('\0', length) returns true, and this is true for string.Empty.Equals(new string('\0', length), StringComparison.InvariantCultureIgnoreCase)) as well.
On the other hand, calling StringComparer.GetHashCode method with string.Empty and new string('\0', length) does not result in same hashcode. The hashcode of string.Empty is 0 and string made out of null characters is not. This contradicts with the statement from IEqualityComparer document.
Current implementation of GetHashCodeOfStringCore method (Which I believe is the actual implementation of string.GetHashCode and StringComparer.GetHashCode methods) seem to always return 0 if the length of the string is 0. if not, it appears to do some pointer magic to get near-unique hashcode for the string.
Shouldn't the GetHashCode(StringComparison) method return '0' for strings made out of null characters as well, if the parameter is not StringComparison.Ordinal/OrdinalIgnoreCase?