C# 字节[]数组上的GetHashCode()

C# 字节[]数组上的GetHashCode(),c#,hash,C#,Hash,在字节[]数组上调用时,GetHashCode()计算什么? 内容相等的两个数据数组不提供相同的散列。在.NET中的数组不覆盖Equals或GetHashCode,因此您将获得的值基本上基于引用相等(即对象中的默认实现)–要实现值相等,您需要滚动自己的代码(或者从第三方找到一些)。如果您试图将字节数组用作字典中的键等,则可能需要实现IEqualityComparer 编辑:这里有一个可重用的数组相等比较器,只要数组元素适当地处理相等,它就可以了。请注意,在将数组用作字典中的键后,不能对其进行变异

字节[]
数组上调用时,
GetHashCode()
计算什么?
内容相等的两个数据数组不提供相同的散列。

在.NET中的数组不覆盖
Equals
GetHashCode
,因此您将获得的值基本上基于引用相等(即
对象中的默认实现)–要实现值相等,您需要滚动自己的代码(或者从第三方找到一些)。如果您试图将字节数组用作字典中的键等,则可能需要实现
IEqualityComparer

编辑:这里有一个可重用的数组相等比较器,只要数组元素适当地处理相等,它就可以了。请注意,在将数组用作字典中的键后,不能对其进行变异,否则即使使用相同的引用,也无法再次找到它

using System;
using System.Collections.Generic;

public sealed class ArrayEqualityComparer<T> : IEqualityComparer<T[]>
{
    // You could make this a per-instance field with a constructor parameter
    private static readonly EqualityComparer<T> elementComparer
        = EqualityComparer<T>.Default;

    public bool Equals(T[] first, T[] second)
    {
        if (first == second)
        {
            return true;
        }
        if (first == null || second == null)
        {
            return false;
        }
        if (first.Length != second.Length)
        {
            return false;
        }
        for (int i = 0; i < first.Length; i++)
        {
            if (!elementComparer.Equals(first[i], second[i]))
            {
                return false;
            }
        }
        return true;
    }

    public int GetHashCode(T[] array)
    {
        unchecked
        {
            if (array == null)
            {
                return 0;
            }
            int hash = 17;
            foreach (T element in array)
            {
                hash = hash * 31 + elementComparer.GetHashCode(element);
            }
            return hash;
        }
    }
}

class Test
{
    static void Main()
    {
        byte[] x = { 1, 2, 3 };
        byte[] y = { 1, 2, 3 };
        byte[] z = { 4, 5, 6 };

        var comparer = new ArrayEqualityComparer<byte>();

        Console.WriteLine(comparer.GetHashCode(x));
        Console.WriteLine(comparer.GetHashCode(y));
        Console.WriteLine(comparer.GetHashCode(z));
        Console.WriteLine(comparer.Equals(x, y));
        Console.WriteLine(comparer.Equals(x, z));
    }
}
使用系统;
使用System.Collections.Generic;
公共密封类阵列质量比较:IEqualityComparer
{
//您可以使用构造函数参数将其设置为每个实例字段
专用静态只读EqualityComparer元素比较器
=EqualityComparer.Default;
公共布尔等于(T[]第一,T[]第二)
{
如果(第一个==第二个)
{
返回true;
}
if(first==null | | second==null)
{
返回false;
}
if(first.Length!=second.Length)
{
返回false;
}
for(int i=0;i
与其他非原语内置类型一样,它只返回任意内容。它绝对不会尝试散列数组的内容。请参见
对象
中,它不会覆盖它。因此,您得到的基本上是
对象
的实现。

如果它不是同一个实例,它将返回不同的哈希值。我猜它是基于以某种方式存储它的内存地址。

简单解决方案

    public static int GetHashFromBytes(byte[] bytes)
    {
        return new BigInteger(bytes).GetHashCode();
    }

仅供参考:如果您使用的是.NET4((IsStructuralEquatable)myArray).GetHashCode(EqualityComparer.Default)对于具有相同内容的两个数组,应给出相同的结果。.Related:@FuleSnabel注意,
IsStructuralEquatable
需要使用非泛型的
IEqualityComparer
接口,这意味着数组中的每个
字节将在hashcode计算期间装箱。不,它不是同一个实例,I presume在这种情况下,散列将是equal@Chesnokov尤里:好的,我已经在我的答案中编辑了一些代码。非常感谢你提供了有用的片段。如果你愿意的话,你的C#depth书有点离题,我会读的。与facebook相比,g+的概念是极好的介绍圈,因为facebook不能分离你的联系人。向每个圈显示不同的用户页面帐户内容和信息会很好,例如,一个人不愿意向他的朋友显示一些工作圈页面内容,反之亦然。你能告诉我我们是否很快就能在那里注册吗?@Chesnokov:恐怕这与这里的主题有点离题,我不能告诉你不管怎么说,都要删除所有即将推出的功能。似乎有一个问题是
GetHashCode
是否应该扫描整个序列。有趣的是,for
Array.IsStructuralEquatable.GetHashCode
只考虑数组的最后八项,牺牲了哈希唯一性以提高速度。我使用Enumerable.SequenceEqual()做了类似的事情.手工编写元素比较代码有什么特别的原因吗?(无可否认,它可能会快一点。)看到这个解决方案让我笑了。干净、优雅。深入挖掘哈希实现最终会调用cough cough GetHashCode();返回int32。@XeorgeXeorge so?@DaveJellison有一个
(2^32)
1发生冲突的可能性,这在大多数情况下是可以忽略的,但在出现哈希代码时必须记住。同意,但这是哈希作为一项规则所固有的。这就像去dictionary.com投诉单词的定义一样。