C#GetHashCode有两个Int16,也只返回Int32?

时间:2012-04-14 18:11:23

标签: c# hash int gethashcode int32

很抱歉将两个问题合并为一个,它们是相关的。

对于HashCode来说,

HashSet等等。据我了解,它们必须是唯一的,而不是更改,并将对象的任何配置表示为单个数字。

我的第一个问题是,对于我的对象,包含两个Int16 ab,我的GetHashCode可以安全地返回a * n + b之类的内容,其中n是很多,我想也许Math.Pow(2, 16)

同样GetHashCode似乎不能特别地返回Int32类型。

32位可以存储,例如,两个Int16,一个unicode字符或16个N,S,E,W指南针方向,它不是很多,甚至像一些小节点图可能对它来说太多了。这是否代表了C#Hash集合的限制?

2 个答案:

答案 0 :(得分:7)

  

据我了解,它们必须是唯一的

不。对于大多数类型而言,它们不可能是唯一的,其可能具有超过2个 32 可能的值。理想情况下,如果两个对象具有相同的哈希码,那么它们不太可能相等 - 但您永远不应该假设它们 相等。重要的是,如果他们有不同的哈希码,他们肯定应该不等

  

我的第一个问题是,对于我的对象,包含两个Int16s a和b,我的GetHashCode返回类似* n + b的东西是安全的,其中n是一个很大的数字,我想也许Math.Pow(2 ,16)。

如果包含两个Int16值,则最简单的方法是使用:

return (a << 16) | (ushort) b;

然后值 将是唯一的。 Hoorah!

  

同样GetHashCode似乎也不明确地返回Int32类型。

是。 DictionaryHashSet等类型需要能够使用固定大小,以便他们可以使用它将值放入存储区。

  

32位可以存储,例如,两个Int16,一个unicode字符或16个N,S,E,W指南针方向,它不是很多,甚至像一些小节点图可能对它来说太多了。这是否代表了C#Hash集合的限制?

如果它 是一个限制,它将是一个.NET限制而不是C#限制 - 但不是,它只是对哈希代码所代表的误解。

Eric Lippert有一个很好的(显然)blog post about GetHashCode,您应该阅读以获取更多信息。

答案 1 :(得分:1)

GetHashCode不是(也不可能)对象的每个实例都是唯一的。以Int64为例;即使散列函数是完美分布的,也会有 two 40亿 Int64散列到每个值,因为哈希码就像你提到的那样,只有Int32

然而,这不是对使用哈希码的集合的限制;它们只是对使用哈希值相同的元素使用存储桶。因此,不能保证对哈希表的查找是单个操作。获取正确的存储桶只需一个操作,但该存储桶中可能有多个项目。