I was reading through the following questions and their answers ---
- Why is ValueType.GetHashCode() implemented like it is?
- How does native implementation of ValueType.GetHashCode work?
--- 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.