-1

I have found some weird behavior with the Vector3D class.

Given two Vector3Ds with rearranged X/Y/Z values (e.g. [0,0,1], [0,1,0] or [3,1,4],[1,3,4]), calling GetHashCode results in the same value. If you check to see if the vectors are equal via .Equals or ==, as expected you see that the two vectors are in fact not equal.

If they are not equal, why would they have the same hash code?

var a = new System.Windows.Media.Media3D.Vector3D(0, 0, 1);
var b = new System.Windows.Media.Media3D.Vector3D(0, 1, 0);

var equal  = a == b; // false
var equals = a.Equals(b); // false
var aHashCode = a.GetHashCode(); // 1072693248
var bHashCode = b.GetHashCode(); // 1072693248
var hashEqual = a.GetHashCode() == b.GetHashCode(); // true

PS: I have also observed this behavior in the Point3D class as well. Perhaps other classes in System.Windows.Media namespace are also affected.

Jeremy Herrman
  • 472
  • 6
  • 14
  • 1
    Do the following. (1) compute the number of possible different values for a vector. (2) compute the number of possible different values for a hash code. (3) If you have n boxes, and some number greater than n pigeons, is it possible to put every pigeon in a box and have no box contain more than one pigeon? – Eric Lippert Jul 24 '14 at 03:08

1 Answers1

4

Two different objects can have the same hash code. Two equal objects alwasy have the same hash code.

As it is stated in MSDN

Two objects that are equal return hash codes that are equal. However, the reverse is not true: equal hash codes do not imply object equality, because different (unequal) objects can have identical hash codes. Furthermore, the .NET Framework does not guarantee the default implementation of the GetHashCode method, and the value this method returns may differ between .NET Framework versions and platforms, such as 32-bit and 64-bit platforms. For these reasons, do not use the default implementation of this method as a unique object identifier for hashing purposes.

Christos
  • 53,228
  • 8
  • 76
  • 108
  • 2
    A hash code is an `int`, so it can take up to 2^32 values. This is limited, and collisions would be too frequent. That's why two objects can have the same hash code even if they're different. In containers that make use of the hash code (`HashSet`, `Dictionary` etc), equality is checked if the hash code matches. – Lucas Trzesniewski Jul 23 '14 at 22:40
  • @LucasTrzesniewski I agree with you dude. That's correct. – Christos Jul 23 '14 at 22:43
  • I get that there can be collisions (although they should be a rare occurrence). The odd thing about this behavior is that the hashcode equality only happens in the case of Vector3Ds with the same set of X Y Z values. For other vectors that don't have the same set of X Y Z values, say [0,0,1] and [1,2,3], you get different hash codes as expected. – Jeremy Herrman Jul 23 '14 at 22:46
  • @JeremyHerrman it's a bit odd, but the fact that for different input you can get the same output explains this. Also, the how different are the two inputs don't affects in general the output of a hash function. You may have a collision or not. – Christos Jul 23 '14 at 22:51
  • +1. Theory - http://en.wikipedia.org/wiki/Pigeonhole_principle. @JeremyHerrman - there are pairs of vectors with values that are not the same (it is theoretically impossible to see other behavior), it is just not obvious to find. If you really interested - look at code for particular `GetHashCode` function and try to compute such pairs, or simply iterate all values :) – Alexei Levenkov Jul 23 '14 at 23:10
  • @JeremyHerrman - The reason the hash codes are the same when the set of X, Y, and Z values is the same is because the implementation of the `GetHashCode()` method for this particular version of `Vector3D` simply XORs all 3 values to compute the hash code, and `1^2^3 == 3^2^1` – John Rasch Jul 24 '14 at 17:56