Array.IStructuralEquatable.GetHashCode中的错误?

Dan*_*ker 6 c# gethashcode

在编写我自己的ByteArray内部使用字节数组的不可变类时,我实现了IStructuralEquatable接口.在我的实现中,我将计算哈希码的任务委托给内部数组.在测试它时,令我惊讶的是,我发现我的两个不同的数组具有相同的结构哈希码,即它们返回相同的值GetHashCode.重现:

IStructuralEquatable array11 = new int[] { 1, 1 };
IStructuralEquatable array12 = new int[] { 1, 2 };
IStructuralEquatable array22 = new int[] { 2, 2 };

var comparer = EqualityComparer<int>.Default;
Console.WriteLine(array11.GetHashCode(comparer));     // 32
Console.WriteLine(array12.GetHashCode(comparer));     // 32
Console.WriteLine(array22.GetHashCode(comparer));     // 64
Run Code Online (Sandbox Code Playgroud)

IStructuralEquatable是一个非常新的和未知的,但我在某处读到它可以用来比较集合和数组的内容.我错了,还是我的.Net错了?

请注意,我不是在谈论Object.GetHashCode!

编辑:所以,我显然是错的,因为不等对象可能有相同的哈希码.但是,不是要求GetHashCode一组有点随机分布的值作为要求吗?经过一些测试后,我发现任何两个具有相同第一个元素的数组都具有相同的哈希值.我仍然认为这是一种奇怪的行为.

Mic*_*zyk 14

你所描述的不是一个bug. GetHashCode()不保证不等对象的唯一哈希值.

来自MSDN:

如果两个对象比较相等,则每个对象的GetHashCode方法必须返回相同的值.但是,如果两个对象的比较不相等,则两个对象的GetHashCode方法不必返回不同的值.

编辑

虽然MSFT .NET实现的GetHashCode()用于Array.IStructuralEquatable在MSDN文档遵循以上的原则,看来作者并没有实现它的目的.

这是"Array.cs"中的代码:

    int IStructuralEquatable.GetHashCode(IEqualityComparer comparer) { 
        if (comparer == null)
            throw new ArgumentNullException("comparer"); 
        Contract.EndContractBlock();

        int ret = 0;

        for (int i = (this.Length >= 8 ? this.Length - 8 : 0); i < this.Length; i++) {
            ret = CombineHashCodes(ret, comparer.GetHashCode(GetValue(0))); 
        } 

        return ret; 
    }
Run Code Online (Sandbox Code Playgroud)

特别注意这一行:

ret = CombineHashCodes(ret, comparer.GetHashCode(GetValue(0)));

除非我弄错了,否则就是0这样i.因此,GetHashCode()对于具有相同max(0,n-8th)元素的数组,始终返回相同的值,其中n是数组的长度.这没有(不违反文档),但显然没有0被替换的那样好i.如果代码只是使用数组中的单个值,也没有理由循环.

  • @MichaelGraczyk:感谢您指出我的Bug已从Connect中删除.我提交了原始问题,但未收到任何删除通知.这是微软非常令人失望的行为; 我现在想知道是否应该审查我提交的案件清单,看看我提交的其他案件是否已被删除...... (3认同)
  • 为了以防万一,我重新填充了这个bug.你可以在这里找到它:https://connect.microsoft.com/VisualStudio/feedback/details/755995/system-array-istructuralequatable-gethashcode-does-not-compute-hash-codes-as-intended (2认同)

Mat*_*nda 5

至少从 .NET 4.6.2 开始,此错误已得到修复。您可以通过Reference Source看到它。

ret = CombineHashCodes(ret, comparer.GetHashCode(GetValue(i)));
Run Code Online (Sandbox Code Playgroud)