Consider the following code:
struct Vec2 : IEquatable
{
double X,Y;
public bool Equals(Vec2 other)
{
return X.Equals(other.X
Hash collisions don't wreak havoc in a dictionary collection. They'll reduce the efficiency if you're unlucky enough to get them, but dictionaries have to cope with them.
Collisions should be rare if at all possible, but they're don't mean the implementation is incorrect. XORs are often bad for the reasons you've given (high collisions) - ohadsc has posted a sample I gave before for an alternative, which should be fine.
Note that it would be impossible to implement Vec2
with no collisions - there are only 232 possible return values from GetHashCode
, but there are rather more possible X and Y values, even after you've removed NaN and infinite values...
Eric Lippert has a recent blog post on GetHashCode
which you may find useful.