我正在尝试散列并保留(散列)object
类型IEnumerable<anotherobject>
,其中包含大约1000个条目。我将生成另一个这样的对象,但这次我想使用两个对象的哈希码来检查条目值的任何变化。
基本上,我想知道GetHashCode()
是否适合这种情况,从性能角度和可靠性角度来看。
如果我必须覆盖它,那么这样做的好方法是,它总是取决于anotherobject
的类型以及Equals
在比较两个anotherobject
时的含义?有通用的方法吗?这个问题是因为我的对象可能很大。
答案 0 :(得分:2)
为不同的对象值和相同的值获取不同的值 对于相同的对象值,始终
这是没有散列函数可以给你的东西。您正在将一个大的(最有可能是无限的)宇宙投射到40亿个值中。肯定会发生碰撞。
当然它取决于类型 - 如果你的类型具有有限数量的值(例如,由两个16位坐标组成的点),你可能可以使用无碰撞的GetHashCode。但字符串,双打或更复杂的类型?否。
散列函数的标准(可取的)属性是,它们不能给你假阴性匹配,但它们可以给你误报匹配(这也是根据.Net的文档,所以任何GetHashCode的实现应该像这样。)
所以标准工作流程是:
请参阅GetHashCode的文档。
编辑:
请注意,默认实现几乎返回一些内部.Net实例ID,所以它几乎不适用于任何东西。您应该意识到,从System.Object的角度来看,只有两个对象是同一个实例才是相同的。
基于值的相等是一种必须由程序员定义的语义。
默认实现返回已确定对象的索引 由公共语言运行时。索引对于实例是唯一的 AppDomain中的一个对象,用于执行引擎的实例。 但是,因为此索引可以在对象之后重用 在垃圾收集期间回收,可以获得相同的 两个不同对象的哈希码。另外,两个对象代表 相同的值只有在完全相同时才具有相同的哈希码 宾语。这种实现对于散列并不是特别有用; 因此,派生类应该重写GetHashCode。
答案 1 :(得分:2)
只有在同一个应用程序执行时,GetHashCode
的返回值才能保证对同一对象的返回值相同;如果您在应用程序执行之间存储哈希代码,则无法保证可靠性。有关详细信息,请参阅MSDN文档System.Object.GetHashCode()(“如果再次运行应用程序,可以[通过GetHashCode]返回不同的哈希代码。”)。事实上,截至2016年3月,哈希码现在记录在不同进程和不同应用程序域之间(即使在同一进程中)可能不同,请参阅GetHashCode文档中的警告框。
永远不应该使用GetHashCode的返回值来确定对象的相等性。呼叫等于也是必要的。
有关实现GetHashCode的指导,请参阅文档的“对继承者的说明”。
关于GetHashCode的默认实现:
GetHashCode方法的默认实现没有 保证不同对象的唯一返回值。而且, .NET Framework不保证默认的实现 GetHashCode方法,它返回的值将是相同的 不同版本的.NET Framework。因此,默认 不得将此方法的实现用作唯一对象 用于散列目的的标识符。
(请注意,这与Java的hashCode()
的默认实现不同,后者被记录为尝试为“不同对象”返回不同的值“尽可能合理”。
因此,如果您需要更稳定的哈希函数,则必须使用自己的哈希函数,更重要的是,记录哈希函数以确保其稳定性并确保用户可以依赖其稳定性。
这里有几种选择,例如MurmurHash3,MD5等。这里重要的是记录您正在使用的哈希函数。