Information Technology Reference
In-Depth Information
We ' r e a l m o s t d o n e . o p e r a t o r = = ( ) i s s i m p l e . A n y t i m e y o u c r e a t e a v a l u e
type, redefine operator==(). The reason is exactly the same as with the
instance Equals() function. The default version uses reflection to compare
the contents of two value types. That's far less efficient than any imple-
mentation that you would write, so write your own. Follow the recom-
mendations in Item 46 to avoid boxing when you compare value types.
Notice that I didn't say that you should write operator==() whenever you
override instance Equals(). I said to write operator==() when you create
value types. You should rarely override operator==() when you create ref-
erence types. The .NET Framework classes expect operator==() to follow
reference semantics for all reference types.
Finally, you come to IStructuralEquality, which is implemented on
System.Array and the Tuple<> generic classes. It enables those types to
implement value semantics without enforcing value semantics for every
comparison. It is doubtful that you'll ever create types that implement
IStructuralEquality. It is needed only for those lightweight types. Imple-
menting IStructuralEquality declares that a type can be composed into a
larger object that implements value-based semantics.
C# gives you numerous ways to test equality, but you need to consider pro-
viding your own definitions for only two of them, along with supporting the
analogous interfaces. You never override the static Object.ReferenceEquals()
and static Object.Equals() because they provide the correct tests, regard-
less of the runtime type. You always override instance Equals() and oper-
ator==() for value types to provide better performance. You override
instance Equals() for reference types when you want equality to mean
something other than object identity. Anytime you override Equals() you
implement IEquatable<T>. Simple, right?
Item 7: Understand the Pitfalls of GetHashCode()
This is the only item in this topic dedicated to one function that you should
avoid writing. GetHashCode() is used in one place only: to define the hash
value for keys in a hash-based collection, typically the HashSet<T> or
Dictionary<K,V> containers. That's good because there are a number of
problems with the base class implementation of GetHashCode(). For ref-
erence types, it works but is inefficient. For value types, the base class ver-
sion is often incorrect. But it gets worse. It's entirely possible that you
cannot write GetHashCode() so that it is both efficient and correct. No
 
 
Search WWH ::




Custom Search