best practices for using value types:
make them immutable; override Equals (the one that takes an object as argument); overload Equals to take another instance of the same value type (e.g. Equals(Point2D other)); overload operators == and !=; override GetHashCode