带字符串键的GetHashCode()

Kin*_*pus 14 .net c# gethashcode c#-2.0

嘿所有,我一直在阅读实现.NET中对象的GetHashCode()覆盖的最佳方法,并且我遇到的大多数答案涉及以某种方式将来自数字类型的成员的数字混合在一起来提出方法.问题是,我有一个使用字母数字字符串作为其键的对象,我想知道是否有一些根本错误的东西只是使用内部ID作为键的字符串的对象,如下所示?


// Override GetHashCode() to return a permanent, unique identifier for
// this object.
static private int m_next_hash_id = 1;
private int m_hash_code = 0;
public override int GetHashCode() {
  if (this.m_hash_code == 0)
    this.m_hash_code = <type>.m_next_hash_id++;
  return this.m_hash_code;
}
Run Code Online (Sandbox Code Playgroud)

是否有更好的方法为使用字母数字字符串作为键的对象提供唯一的哈希码?(不,字母数字字符串的数字部分不是唯一的;其中一些字符串实际上根本没有数字.)任何想法都将不胜感激!

Jon*_*n B 22

您可以调用GetHashCode()在对象中使用的非数字值.

private string m_foo;
public override int GetHashCode()
{
    return m_foo.GetHashCode();
}
Run Code Online (Sandbox Code Playgroud)

  • 对象改变了.哈希码*也必须改变*. (6认同)
  • @King Skippus:哈希码不应该改变的原因是它们有助于*识别*一个对象。但如果该对象的字段发生变化,则它不是同一个对象。它可能是同一个实例,但不再是相同的数据。您不会期望 `Equals()` 为具有不同键字段的两个不同实例返回 true 吗?那么为什么要尝试阻止哈希值改变呢?您当然可以*存储*散列,但是如果您这样做的原因是将可变类型作为键存储在字典中,那么正确的解决方案是避免这种情况。 (2认同)

LBu*_*kin 21

这不是为对象生成哈希的好模式.

重新理解GetHashCode()的目的很重要 - 它是一种生成对象标识属性的数字表示的方法.散列码用于允许对象充当字典中的键,并在某些情况下加速复杂类型之间的比较.

如果您只是生成一个随机值并将其称为哈希码,则您没有可重复性.具有相同键字段的另一个实例将具有不同的哈希代码,并且将违反HashSet,Dictionary等类所期望的行为.

如果您已在对象中拥有标识字符串成员,则只返回其哈希代码.

为实施者在MSDN文档GetHashCode()是一个必须阅读的人,关于覆盖该方法的计划:

对实施者的说明

哈希函数用于快速生成对应于对象值的数字(哈希码).散列函数通常特定于每个类型,并且为了唯一性,必须至少使用一个实例字段作为输入.

哈希函数必须具有以下属性:

如果两个对象比较相等,则每个对象的GetHashCode方法必须返回相同的值.但是,如果两个对象的比较不相等,则两个对象的GetHashCode方法不必返回不同的值.

为对象GetHashCode方法必须一致,只要没有修改确定的该对象的Equals方法返回值的对象的状态返回相同的散列码.请注意,这仅适用于当前应用程序的执行,并且如果再次运行应用程序,则可以返回不同的哈希代码.

为获得最佳性能,哈希函数必须为所有输入生成随机分布.

例如,String类提供的GetHashCode方法的实现为相同的字符串值返回相同的哈希码.因此,如果两个String对象表示相同的字符串值,则它们返回相同的哈希码.此外,该方法使用的所有字符的字符串中生成相当随机的分布输出,即使当输入在一定范围内是集群(例如,许多用户可能具有仅包含下部128个ASCII字符的字符串,即使一个字符串可以包含任何65,535个Unicode字符).