GetHashCode Silverlight / WP7.1中的方法可靠性

时间:2011-11-12 09:44:34

标签: c# silverlight windows-phone-7 gethashcode

我正在尝试散列并保留(散列)object类型IEnumerable<anotherobject>,其中包含大约1000个条目。我将生成另一个这样的对象,但这次我想使用两个对象的哈希码来检查条目值的任何变化。

基本上,我想知道GetHashCode()是否适合这种情况,从性能角度和可靠性角度来看。

如果我必须覆盖它,那么这样做的好方法是,它总是取决于anotherobject的类型以及Equals在比较两个anotherobject时的含义?有通用的方法吗?这个问题是因为我的对象可能很大。

2 个答案:

答案 0 :(得分:2)

  

为不同的对象值和相同的值获取不同的值   对于相同的对象值,始终

这是没有散列函数可以给你的东西。您正在将一个大的(最有可能是无限的)宇宙投射到40亿个值中。肯定会发生碰撞。

当然它取决于类型 - 如果你的类型具有有限数量的值(例如,由两个16位坐标组成的点),你可能可以使用无碰撞的GetHashCode。但字符串,双打或更复杂的类型?否。

散列函数的标准(可取的)属性是,它们不能给你假阴性匹配,但它们可以给你误报匹配(这也是根据.Net的文档,所以任何GetHashCode的实现应该像这样。)

所以标准工作流程是:

  1. 比较两个对象的哈希值。如果为false,则对象不相等。
  2. 否则进行完全相等的测试。
  3. 请参阅GetHashCode的文档。

    编辑:

    请注意,默认实现几乎返回一些内部.Net实例ID,所以它几乎不适用于任何东西。您应该意识到,从System.Object的角度来看,只有两个对象是同一个实例才是相同的。

    基于值的相等是一种必须由程序员定义的语义。

      

    默认实现返回已确定对象的索引   由公共语言运行时。索引对于实例是唯一的   AppDomain中的一个对象,用于执行引擎的实例。   但是,因为此索引可以在对象之后重用   在垃圾收集期间回收,可以获得相同的   两个不同对象的哈希码。另外,两个对象代表   相同的值只有在完全相同时才具有相同的哈希码   宾语。这种实现对于散列并不是特别有用;   因此,派生类应该重写GetHashCode。

    See this.

答案 1 :(得分:2)

只有在同一个应用程序执行时,GetHashCode的返回值才能保证对同一对象的返回值相同;如果您在应用程序执行之间存储哈希代码,则无法保证可靠性。有关详细信息,请参阅MSDN文档System.Object.GetHashCode()(“如果再次运行应用程序,可以[通过GetHashCode]返回不同的哈希代码。”)。事实上,截至2016年3月,哈希码现在记录在不同进程和不同应用程序域之间(即使在同一进程中)可能不同,请参阅GetHashCode文档中的警告框。

永远不应该使用GetHashCode的返回值来确定对象的相等性。呼叫等于也是必要的。

有关实现GetHashCode的指导,请参阅文档的“对继承者的说明”。

关于GetHashCode的默认实现:

  

GetHashCode方法的默认实现没有   保证不同对象的唯一返回值。而且,   .NET Framework不保证默认的实现   GetHashCode方法,它返回的值将是相同的   不同版本的.NET Framework。因此,默认   不得将此方法的实现用作唯一对象   用于散列目的的标识符。

(请注意,这与Java的hashCode()的默认实现不同,后者被记录为尝试为“不同对象”返回不同的值“尽可能合理”。

因此,如果您需要更稳定的哈希函数,则必须使用自己的哈希函数,更重要的是,记录哈希函数以确保其稳定性并确保用户可以依赖其稳定性。

这里有几种选择,例如MurmurHash3,MD5等。这里重要的是记录您正在使用的哈希函数。