StringComparer.InvariantCultureIgnoreCase Equals与GetHashCode不同意对于相等的对象

Ian*_*att 8 .net c#

StringComparer.InvariantCultureIgnoreCase Equals为""vs"\ 0"返回true,但GetHashCode为这两个字符串返回不同的值.这是一个错误吗?

var sc = StringComparer.InvariantCultureIgnoreCase;
string s1 = "";
string s2 = "\0";
Console.WriteLine( sc.Equals(s1, s2)  );
Console.WriteLine( sc.GetHashCode(s1) );
Console.WriteLine( sc.GetHashCode(s2) );
Run Code Online (Sandbox Code Playgroud)

回报

True
0
-1644535362
Run Code Online (Sandbox Code Playgroud)

我认为GetHashCode应该为'equal'字符串返回相同的值,所以这是一个错误吗?

Dan*_*ite -3

这两个字符串按位不相等。它们有 2 种不同的长度。因此,这里的哈希码算法是合理的。

\0进行比较时必须忽略字符串比较算法。我查看了源代码:它正在执行某种加/减比较算法来找出情况是否不同。

GetHashCode仅意味着值可能相等,但不一定相等。相反的情况并不总是正确,您可以覆盖任何类型的==运算符或,并在哈希码不一致时.Equals生成它。true

这里是GetHashCode. 看起来它正在使用原始字节进行计算。

您可能偶然发现了 .NET 库中的一个不起眼的错误,但我猜测这是一个边缘情况。

再说一遍 - 您正在使用字符串比较器。不是string.Equals方法或string.GetHashCode。请注意,Console.WriteLine("\0".Equals(""));产生false.

如果您想要一个能够使其一致的字符串比较器,我相信StringComparer.OrdinalIgnoreCase可以做到这一点,因为它单独查看每个字符,而不是对值进行整理。 看起来两者都只是采用相同的字符比较方法。

  • 方法签名不是接口契约的唯一部分。预期行为也是契约的一部分,尽管 C# 没有提供在代码中表达这部分的方法。如果你违反了这条规则,那么你就违反了执行。 (4认同)
  • 我不明白。在批量比较中,仅对具有相等哈希值的对调用“Equals()”,那么如何允许比较器为相等的字符串返回不相等的哈希值呢? (2认同)
  • *相反并不总是正确的,您可以覆盖任何类型的“==”运算符或“.Equals”,并在哈希码不一致时生成“true”。* [文档](https:// learn.microsoft.com/en-us/dotnet/api/system.collections.generic.iequalitycomparer-1.gethashcode?view=netframework-4.7.2#notes-to-implementers)似乎不同意:*需要实现确保如果“Equals(T, T)”方法对两个对象“x”和“y”返回“true”,则“GetHashCode(T)”方法为“x”返回的值必须等于返回的值对于“y”。* (2认同)