1

I was attempting to use the GetHashCode() value to determine if an object has changed after it's been validated via ajax calls in an ASP.NET MVC application. However, I noticed that this did not work because the hash code value when returned during validation would be different than the hash code generated when the object was created again from the model binding with the same values in another request after the validation request. I was able to solve this problem by creating a SHA hash instead, but I'm curious on why I was seeing this behavior.

I know that hash codes generated from GetHashCode() should not be persisted and can differ on different platforms and over time. I thought that the time period was short enough when I first came up with this idea since these two calls were made in milliseconds of each other and when debugging I confirmed that the model contained the exact same values, but still produced a different hash code.

I'm curious about why this behavior is exhibited. Why would this happen even though this is a single run of the application, albeit a web application? Does this have to do with the ASP.NET life cycle?

In case needed here's the class & GetHashCode implementation I was using:

class DispositionSubmission
{
    [Display(Name = "Client")]
    [Required(AllowEmptyStrings = false, ErrorMessage = "Client is required.")]
    public string ClientId { get; set; }
    public string Carrier { get; set; }
    public Dictionary<string, string> DispositionInfo { get; set; }
    public DispositionType Type { get; set; } //int based enum

...

    public override int GetHashCode()
    {
        unchecked
        {
            int hash = (int)15485863;
            int bigPrime = (int)15485867;

            hash = hash * bigPrime ^ ClientId.GetHashCode();
            hash = hash * bigPrime ^ (Carrier ?? "").GetHashCode();
            hash = hash * bigPrime ^ DispositionInfo.GetHashCode();
            hash = hash * bigPrime ^ Type.GetHashCode();

            return hash;
        }
    }
}

2 Answers 2

5

DispositionInfo does not have a type that overrides GetHashCode(). Two identical dictionaries with the same objects in them will have different hash codes.

You will need to adjust your GetHashCode() to either not include the dictionary or make it more complex to get the hash code of each key and value in the dictionary and add them up.

Sign up to request clarification or add additional context in comments.

4 Comments

Ah! That makes sense! Smacks head against desk
I would lean more toward excluding the dictionary, GetHashCode is supposed to be a fast returning function and going through a entire dictionary if large could be quite slow.
It will rarely have more than 20 key-value pairs, but I need to include it because I was using this to make sure nothing changed (including the key-value pairs in the dictionary) was the purpose of using the hash code. Serializing it and generating a SHA-1 hash did the trick. Not the fastest performing method, but fast enough for what it's being used for.
GetHashCodes() are not for checking if anything has changed, it is only for checking which HashBucket the object should go in when using a HashSet or Dictionary. Or as a quick "Pre-Check" to doing a .Equals( if the equals operator is slow (like it has to check the entire contents of a collection for equality)
1

GetHashCode will return the same result for the exact same object. If the object has been reallocated, it doesn't matter if you have identical values in all fields, you will get a different result. This is because what you're really using is Object.GetHashCode(), which knows nothing about its other fields anyway.

This behavior is important because if you're using the hash as a way to refer to the object, changing any of its values would make it impossible to reference again.

If you want to have behavior where objects with identical fields have the same hash code, you'll need to implement it yourself.

Edit: To clarify: DispositionInfo, the dictionary, specifically exhibits this behavior. The other fields do not, because they are designed to be immutable (string, int, etc.) Consider getting the hash a different way, or overriding GetHashCode with a custom class that inherits from Dictionary<string, string>.

2 Comments

I referred to the incorrect override. He is referring to the response before the edit.
@SaxxonPike saw you fixed it and removed my comment/downvote

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.