如何为结构实现base.GetHashCode()?

时间:2017-10-30 06:55:47

标签: c# struct hashcode

我最近在struct看到了这段代码,我想知道base.GetHashCode实际上做了什么。

    public override int GetHashCode()
    {
        var hashCode = -592410294;
        hashCode = hashCode * -1521134295 + base.GetHashCode();
        hashCode = hashCode * -1521134295 + m_Value.GetHashCode();
        return hashCode;
    }

2 个答案:

答案 0 :(得分:7)

coreclr repo有this comment

  

动作:我们返回哈希码的算法有点复杂。我们看   对于第一个非静态字段并获取它的哈希码。如果类型没有   非静态字段,我们返回该类型的哈希码。我们无法接受   静态成员的哈希码,因为如果该成员的类型与   原始类型,我们将以无限循环结束。

然而,代码并不存在,而且看起来并非相当会发生什么。样品:

using System;

struct Foo
{
    public string x;
    public string y;
}

class Test
{
    static void Main()
    {
        Foo foo = new Foo();
        foo.x = "x";
        foo.y = "y";
        Console.WriteLine(foo.GetHashCode());
        Console.WriteLine("x".GetHashCode());
        Console.WriteLine("y".GetHashCode());
    }
}

我的盒子上的输出:

42119818
372029398
372029397

更改y的值似乎不会更改foo的哈希码。

但是,如果我们改为使用字段int值,那么第一个字段会影响输出。

简而言之:这很复杂,您可能不应该依赖它在运行时的多个版本中保持不变。除非您真的非常确信您不需要将自定义结构用作基于哈希的字典/集中的键,否则我强烈建议覆盖GetHashCode和{ {1}}(并实施Equals以避免装箱)。

答案 1 :(得分:1)

结构的基类是ValueType类,源代码在线。他们帮助留下了描述其工作原理的评论:

ValueType.GetHashCode

/*=================================GetHashCode==================================
**Action: Our algorithm for returning the hashcode is a little bit complex.  We look
**        for the first non-static field and get it's hashcode.  If the type has no
**        non-static fields, we return the hashcode of the type.  We can't take the
**        hashcode of a static member because if that member is of the same type as
**        the original type, we'll end up in an infinite loop.
**Returns: The hashcode for the type.
**Arguments: None.
**Exceptions: None.
==============================================================================*/
[System.Security.SecuritySafeCritical]  // auto-generated
[ResourceExposure(ResourceScope.None)]
[MethodImplAttribute(MethodImplOptions.InternalCall)]
public extern override int GetHashCode();