如何为字符串生成唯一的哈希码

时间:2012-01-19 11:06:44

标签: c#

是否有任何函数可以为同一个字符串提供相同的哈希码?

我在创建2个不同的字符串(但内容相同)时遇到问题,但它们的哈希码不同,因此未在Dictionary中正确使用。

我想知道当密钥是字符串时GetHashCode()使用的Dictionary函数。

我正在建造我的:

public override int GetHashCode()
{
   String str = "Equip" + Equipment.ToString() + "Destiny" + Destiny.ToString();
   return str.GetHashCode();
}

但它会为使用此代码的每个实例产生不同的结果,尽管字符串的内容是相同的。

1 个答案:

答案 0 :(得分:14)

你的标题要求一件事(唯一的哈希码)你的身体要求不同的东西(一致的哈希码)。

你声称:

  

我在创建2个不同的字符串时遇到了麻烦(但内容相同),它们的哈希码不同,因此未在字典中正确使用。

如果字符串真正具有相同的内容,则根本不会发生。你的诊断错误了。检查字符串中的不可打印字符,例如尾随Unicode“null”字符:

string text1 = "Hello";
string text2 = "Hello\0";

此处text1text2可能会在某些情况下以相同的方式打印,但我希望它们有不同的哈希码。

请注意,哈希码保证是唯一的,不能 ...只有2个 32 可能的哈希码从GetHashCode返回,但超过2 32 可能的不同字符串。

另请注意,相同的内容保证在不同的运行中生成相同的哈希码,即使是相同的可执行文件 - 您也不应该持久化哈希码任何地方。例如,我相信32位.NET 4和64位.NET 4 CLR为字符串生成不同的哈希码。但是,您声称这些值未在Dictionary中正确存储的说法表明这是在一个过程中 - 应该一致。

正如评论中所述,您完全有可能错误地覆盖Equals。我还建议你构建哈希码的方法不是很好。我们不知道EquipmentDestiny的类型是什么,但我建议你应该使用类似的内容:

public override int GetHashCode()
{
    int hash = 23;
    hash = hash * 31 + Equipment.GetHashCode();
    hash = hash * 31 + Destiny.GetHashCode();
    return hash;
}

这是我通常用于哈希码的方法。 Equals会看起来像:

public override bool Equals(object other)
{
    // Reference equality check
    if (this == other)
    {
        return true;
    }         
    if (other == null)
    {
        return false;
    }
    // Details of this might change depending on your situation; we'd
    // need more information
    if (other.GetType() != GetType())
    {
        return false;
    }

    // Adjust for your type...
    Foo otherFoo = (Foo) other;

    // You may want to change the equality used here based on the
    // types of Equipment and Destiny
    return this.Destiny == otherFoo.Destiny &&
           this.Equipment == otherFoo.Equipment;
}