2009-02-03 67 views
15

下面是一个覆盖Object.Equals()的示例实现,用于应用程序中所有其他实体从中派生的实体基类。实体类的GetHashCode()的正确实现是什么?

所有的实体类都有属性Id,它是一个可为空的int。 (这是无论什么表的实体类对应的主键。)

public override bool Equals(object obj) 
     { 
      if (obj == null || GetType() != obj.GetType()) 
       return false; 

      if (base.Equals(obj)) 
       return true; 

      return Id.HasValue && ((EntityBase) obj).Id.HasValue && 
        Id.Value == ((EntityBase) obj).Id.Value; 
     } 

鉴于此实现equals()方法中,你如何正确地实现GetHashCode()方法?

+0

对于记录来说,对于一个ID有一个可为空的int是一个可怕的想法。 ID应该几乎总是GUID,绝对不能为空。 – 2014-08-28 15:52:18

回答

23

如果你从一些已经覆盖GetHashCode获得我实现它:

public override int GetHashCode() 
{ 
    unchecked 
    { 
     int hash = 37; 
     hash = hash * 23 + base.GetHashCode(); 
     hash = hash * 23 + Id.GetHashCode(); 
     return hash; 
    } 
} 

身份证件的空值将Id.GetHashCode返回0()。

如果你的类只是从Object派生,我刚刚回到Id.GetHashCode() - 你想在你的哈希码的object.GetHashCode实施,基本上最终被对象标识。

请注意,如果两个实体都没有Id,但您的相等定义将不会返回true但是两个对象都返回相同的哈希码。你不妨考虑改变你的Equals实现。

+9

对于那些想知道的问题,就像我做的那样:23和37是任意数字,它们是共素数。乔恩在这里回答了类似的答案:http://www.eggheadcafe.com/software/aspnet/29483139/override-gethashcode.aspx – 2009-02-03 17:57:49

1

如果Id属性在实例的生命周期中不可改变(或至少在需要使用其哈希值的时间内,例如在对象位于地图或其他集合中时需要使用GetHashCode(),散列)。

假设它是这样,您可以使用Id的值作为所有有效值的哈希值,然后对null使用固定哈希值。我不记得最适合这个的是什么,但是我会假设一个随机选择的值为null(在编译之前随机选择,不是在运行时)或者值的有效值的中间值(即0和int之间的一半。最大)。

+1

它不一定是永生不变的 - 只能从第一次插入地图或其他地方的时候开始。可以创建一个实例,解决它,将其放入地图,然后*停止混乱。 – 2009-02-03 17:48:42

+0

这是一个公平的观点。我会做一个编辑。 – 2009-02-03 17:51:41

2

什么乔恩斯基特回答是一个很好的解决方案,但是,你可能要添加一个未检查的代码块,使整数溢出

unchecked 
{ 
    int hash = ...; 
    return hash 
} 

https://msdn.microsoft.com/en-us/library/khy08726(v=vs.140).aspx

如果没有选中,也不指定选中,默认上下文取决于外部因素,如编译器选项。

我还想补充一点,在POCO上使用base.GetHashCode()将会调用默认的object.GetHashCode。这绝对不是你想要的...

2

如何使用该类型作为散列码的一部分?
这是一个很好的实现吗?

public class Foo 
{ 
    public int Id { get; set; } 

    // other properties here 
    // ...... 

    public override int GetHashCode() 
    { 
     int hash = 37; 
     hash = hash * 23 + typeof(Foo).GetHashCode(); 
     hash = hash * 23 + Id.GetHashCode(); 
     return hash; 
    } 
} 
相关问题