.Net哈希码不再持久?

时间:2009-10-14 10:53:47

标签: c# .net hashcode

我有一个API,其中各种类型都有自定义哈希码。这些哈希码基于获取相关对象的字符串表示的哈希值。使用了各种腌制技术,以便尽可能使Hash代码发生冲突,并且具有等效字符串表示的不同类型的对象具有不同的Hash代码。

显然,由于哈希码基于字符串,因此存在一些冲突(无限字符串与32位整数的有限范围)。我使用基于字符串表示的哈希,因为我需要哈希来保持会话,特别是用于对象的数据库存储。

突然间,今天我的代码开始为Objects生成不同的哈希码,这些哈希码会破坏各种各样的东西。它今天早些时候工作,我没有触及哈希码生成中涉及的任何代码。

我知道.Net文档允许在.Net框架版本之间实现哈希码的更改(以及32位和64位版本之间),但我没有更改框架版本,也没有框架更新最近我记得

任何想法,因为这看起来很奇怪?

修改

生成哈希码如下:

//Compute Hash Code
this._hashcode = 
   (this._nodetype + this.ToString() + PlainLiteralHashCodeSalt).GetHashCode();

2 个答案:

答案 0 :(得分:3)

如果Object.ToString()没有被覆盖,那么StampedeXV在其评论中建议ToString()默认返回完全限定名称。

  1. 如果未覆盖ToString(),则更改名称空间(或类名称)会更改此值。
  2. 显然,覆盖ToString()会改变它。
  3. 确切地检查_nodeType修改的方式和位置。
  4. PlainLiteralHashCodeSalt仍然是个谜(我认为它是一个常数字符串)。
  5. 没有人保证String.HashCode()不会改变,因此您至少可以使用Reflector来获取方法的来源并将其包含在您的库中。这是我通常会推荐的内容,但您不希望将来依赖此内容。
  6. 毋庸置疑,您应该跟踪所有3个值(_nodeType,this.ToString()和salt string)以检查它们是否未更改。如果您可以恢复到可以使用的旧版本,那么您就在那里。

    除此之外,不建议持久化哈希码。如果这与性能相关,请注意由数据库负责处理索引和散列。既然你不能保证它是独一无二的,那么它也不是一个GUID。那么重点是什么呢?

    但是因为它已经存在于数据库中,所以现在主要关注的是如何恢复HashCode实现。

答案 1 :(得分:1)

您说您使用此哈希码进行持久化。对于当前的实现,这是一个坏主意,因为您使用ToString()函数来生成哈希码。此函数的结果与持久性无关,也许开发人员需要为GUI设计或任何原因和忘记更改它,它也用于持久性。
在你的情况下,我会查看ToString()方法的结果,也许它已经改变了。这可以通过改变文化或将对象移动到另一个命名空间来实现 - 只需看看,也许你找到了理由。