Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I generate a unique hashcode for a string

Tags:

c#

Is there any function, that gives me the same hashcode for the same string?

I'm having trouble when creating 2 different strings (but with the same content), their hashcode is different and therefore is not correctly used in a Dictionary.

I would like to know what GetHashCode() function the Dictionary uses when the key is a string.

I'm building mine like this:

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

But it's producing different results for every instance that uses this code, despite the content of the string being the same.

like image 994
RagnaRock Avatar asked Jan 19 '12 11:01

RagnaRock


1 Answers

Your title asks for one thing (unique hash codes) your body asks for something different (consistent hash codes).

You claim:

I'm having trouble when creating 2 different strings (but with the same content), their hashcode is different and therefore is not correctly used in a Dictionary.

If the strings genuinely have the same content, that simply won't occur. Your diagnostics are wrong somehow. Check for non-printable characters in your strings, e.g trailing Unicode "null" characters:

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

Here text1 and text2 may print the same way in some contexts, but I'd hope they'd have different hash codes.

Note that hash codes are not guaranteed to be unique and can't be... there are only 232 possible hash codes returned from GetHashCode, but more than 232 possible different strings.

Also note that the same content is not guaranteed to produce the same hash code on different runs, even of the same executable - you should not be persisting a hash code anywhere. For example, I believe the 32-bit .NET 4 and 64-bit .NET 4 CLRs produce different hash codes for strings. However, your claim that the values aren't being stored correctly in a Dictionary suggests that this is within a single process - where everything should be consistent.

As noted in comments, it's entirely possible that you're overriding Equals incorrectly. I'd also suggest that your approach to building a hash code isn't great. We don't know what the types of Equipment and Destiny are, but I'd suggest you should use something like:

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

That's the approach I usually use for hash codes. Equals would then look something like:

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;
}
like image 144
Jon Skeet Avatar answered Oct 08 '22 11:10

Jon Skeet