2

I was reading through the following questions and their answers ---

--- which basically indicate a naturally correct and usually efficient implementation of GetHashCode for System.ValueType is not easy. An answer at one of the linked posts briefly indicates that GetHashCode has a bug with respect to decimal fields of structs, e.g.:

struct Test { public decimal value; }

static void Main() {
    var d1 = 1.0m;
    var d2 = 1.00m; // Numerically equal but has different bits
    var t1 = new Test() { value = d1 };
    var t2 = new Test() { value = d2 };
    Console.WriteLine(Equals(d1, d2)); // True
    Console.WriteLine(d1.GetHashCode() == d2.GetHashCode()); // True
    Console.WriteLine(Equals(t1, t2)); // True
    Console.WriteLine(t1.GetHashCode() == t2.GetHashCode()); // False!
}

For this decimal-containing struct, ValueType.GetHashCode violates the Equals/GetHashCode relationship. To be clear, that's the following (a summary from MSDN):

Two objects that are equal return hash codes that are equal.

Now, note the documentation of ValueType.Equals (Framework 4.5):

If none of the fields of the current instance and obj are reference types, the Equals method performs a byte-by-byte comparison of the two objects in memory.

So this is evidently not true, which was also observed here.

My (revised) question: Is this a bug in Equals or a bug in GetHashCode? From what other posts are saying, it seems like the bug is in GetHashCode, but MSDN's possible documentation defect makes it very unclear.

Community
  • 1
  • 1
William
  • 1,993
  • 2
  • 23
  • 40
  • There's more wrong here. If it really did take the hash code of the first non-static field, then if you check, `d1.GetHashCode() == d2.GetHashCode()` so that can't be true (and yes, I verified by also doing `t1.value.GetHashCode()` and same for t2. – Lasse V. Karlsen May 16 '14 at 16:04
  • 1
    This exact "bug" is already addressed in one of the post you included in the question. What exactly is the question? – rae1 May 16 '14 at 16:05
  • Also, the documentation for GetHashCode mentions value types and differs from that comment in the code: http://msdn.microsoft.com/en-us/library/system.object.gethashcode.aspx - it says it computes the hash code using all the fields of the value type. This, again, does not explain the difference above. – Lasse V. Karlsen May 16 '14 at 16:07
  • 1
    @rae1 The question is why `t1.GetHashCode() == t2.GetHashCode()` returns `false`, and thus if this isn't a broken implementation of GetHashCode (or equals, if the value types are meant to be different). – Lasse V. Karlsen May 16 '14 at 16:07
  • @LasseV.Karlsen Based on [the attached post](http://stackoverflow.com/a/5927853/1250033) this has already been reported as a bug in the `GetHashCode` implementation. – rae1 May 16 '14 at 16:33
  • @rae1 You're right to ask for clarification, I was asking about the apparent violation of the Equals/GetHashCode relationship. That's not much different, though, as the claim that GetHashCode's behavior is a bug (which the linked post contains and which I mostly trust) implies that the relationship violation is a bug as well. Lasse is right to point out that the other aspect of my question was whether it's actually Equals that should return false in the example. I doubted (and still doubt) that, but I wasn't sure. Sorry for the clumsy question, I updated my post a bit. Thanks. – William May 16 '14 at 20:11

0 Answers0