0

我正在开发一个简单的 2D 环境,绘制的每个对象,例如线条、矩形和...通过调用 GetHashCode() 获取唯一的 id

现在,我在MSDN 页面上注意到它不能保证其结果是唯一的:

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

GetHashCode()现在,问题是除了方法之外还存在哪些其他选项?

谢谢,阿米特

4

4 回答 4

3

也许最好完全摆脱哈希码?GetHashCode非常适合快速轻松地修复,但如果您需要对象的真实 ID,那么您应该创建真实 ID。像 32/64 位自动递增整数之类的东西可能就足够了。

虽然哈希码的冲突率与哈希的长度相关,但仍不能保证在发生冲突之前达到可能的最大唯一哈希数。如果您自己管理 ID,则可以提前计划有足够的可用 ID。

另外-您对框架版本之间不同的 GetHashCode() 的评论。我只能想象,如果您将散列保存到某种保存文件中,然后尝试重新加载它们,却发现它们与正在运行的程序的散列不匹配,因为它们已被保存,我只能想象这对您的情况很重要通过不同版本的框架。如果是这种情况,我会建议您更多地在对象上创建和管理 ID。

于 2012-09-29T01:36:54.823 回答
3

您需要生成自己的唯一 ID

如果您的对象具有自然键,则有时可以从对象属性中派生唯一 ID。
如果对象没有自然键,则必须生成唯一 ID,您通常会将唯一 ID 传递给构造函数中的对象。

GetHashCode 是较差的唯一 ID,因为它不能保证是唯一的。
在内部,.NET 不使用 GetHashCode 来实现唯一性。
.NET 在内部使用 GetHashCode 来加速相等比较和 HashBuckets。

如果要生成自己的唯一 ID,则应覆盖 GetHashCode 和 Equals。
这样,.NET 可以使用您的唯一标识符进行相等比较。

.NET GetHashCode() 不需要也不保证是唯一的。
.NET GetHashCode() 不仅限于 Int32。
.NET GetHashCode() 是 Int32。

如果 GetHashCode 不相等,则两个对象不相等。
如果 GetHashCode 相等,则两个对象可能相等也可能不相等。Equals 是决胜局。
对于速度,首先比较 GetHashCode。GetHashCode 也用于 hashbuckets,以提高 HashSet 和 Dictionary 等集合的速度。

如果哈希是唯一的,那么它被认为是完美的哈希。

经典例子

class Point: object 
{
   protected int x, y;

   public Point(int xValue, int yValue)
   {
        x = xValue;
        y = yValue;
   }
   public override bool Equals(Object obj) 
   {
      // Check for null values and compare run-time types.
      if (obj == null || GetType() != obj.GetType()) 
         return false;

      Point p = (Point)obj;
      return (x == p.x) && (y == p.y);
   }
   public override int GetHashCode() 
   {
      return x ^ y;
   }
}

由于 Point 具有 Int32 X Int32 可能值,因此显然它不能用单个 Int32 唯一标识。GetHashCode 仍然是有价值的并且是必需的。只有 1/Int32 的机会需要更昂贵的 Equals,并且 GetHashCode 用于哈希桶。

考虑简单点

class Point: object 
{
   protected byte x, y;

   public Point(byte xValue, byte yValue)
   {
        x = xValue;
        y = yValue;
   }
   public override bool Equals(Object obj) 
   {
      // Check for null values and compare run-time types.
      if (obj == null || GetType() != obj.GetType()) 
         return false;

      Point p = (Point)obj;
      return (x == p.x) && (y == p.y);
   }
   public override int GetHashCode() 
   {
      return (x * 256) + y;
   }
}

在这个简单点中,GetHashCode 将唯一标识对象。您不能覆盖其中之一。必须不覆盖或覆盖两者。

于 2012-09-29T01:37:13.947 回答
2

这取决于您使用唯一 ID 的目的。听起来您正在使用来识别对象实例,这可能意味着哈希码不是您想要的。

如果两个对象彼此是 .Equals(),则它们应该具有相同的哈希码,但正如您所发现的,相反的情况并非如此(具有相同的哈希码并不意味着它们是 .Equals())。

您需要唯一 ID 做什么?如果您不使用哈希码将对象放入查找中,则最好为它们分配一个唯一的 ID,如 Guid ( var uniqueId = Guid.NewGuid())。

于 2012-09-29T01:39:56.890 回答
1

没有哈希函数可以保证返回值的唯一性。

这取决于碰撞的概率有多小。

GetHashCode() 返回一个 32 位整数,这可能不足以假设唯一性。考虑其他算法,如 SHA-1、SHA-2,其哈希长度较长,碰撞概率远低于 32 位整数。

于 2012-09-29T01:26:46.493 回答