The VS2005 documentation Guidelines for Overloading Equals() and Operator == (C# Programming Guide) states in part
Overriding operator == in non-immut
I don't understand your concerns about GetHashCode in regards to HashSet. GetHashCode just returns a number that helps HashSet internally store and lookup values. If the hash code for an object changes the object doesn't get removed from HashSet, it just won't be stored in the most optimal position.
EDIT
Thanks to @Erik J I see the point.
The HashSet is a performance collection and to achieve that performance it relies completely on GetHashCode being constant for the life of the collection. If you want this performance then you need to follow these rules. If you can't then you'll have to switch to something else like List