String type; because it is treated like an object that has its own hash…code calculation implementation。 Notice in the implementations of the Append() methods how a calculation is performed and then added to the data member _runningTotal。 The return value is a Me reference; so that the methods can be chained together。 This allows a client to use the HashCodeAutomater class; as the following GetHashCode() implementation demonstrates: …………………………………………………………Page 304…………………………………………………………… 282 CH AP T E R 1 0 ■ L E A R N I N G A B OU T P E R S IS TE N CE Class HashcodeExample Public value As Integer Public buffer As String Public Sub New (ByVal val As Integer; ByVal buf As String) value = val buffer = buf End Sub Public Overrides Function GetHashCode() As Integer Return New HashCodeAutomater() 。Append(value) 。Append(buffer)。toHashCode() End Function End Class The implementation of HashcodeExample has two data members: value and buffer。 The two data members make up the class’s state。 Not all data members are used when calculating a class instance’s hash…code value。 For example; if HashcodeExample had a data member that referenced a database connection; it should not be used when calculating the hash code; because the database connection is the type used to get the state and does not influence the state—it is a means to an end。 Implementing Equals() Once the GetHashCode() method has been implemented; the Equals() method can be implemented: Public Overrides Function Equals(ByVal obj As Object) As Boolean If TypeOf(obj) Is HashCodeExample Then If obj。GetHashCode() = Me。GetHashCode() Then Return True End If End If Return False End Function Because the rule for GetHashCode() is that two object instances with identical hash…code values must return the same value; it makes sense to implement Equals() using GetHashCode()。 However; what started out as a good idea turns out to be a bad idea; as the following illustrates: Dim s1 As String = 〃Hello〃 Dim s2 As String = 〃World〃 Dim x1 As Integer = 17 * 17 + s1。GetHashCode() Dim x2 As Integer = 17 * 17 + s2。GetHashCode() Dim h1 As HashCodeExample = New HashCodeExample (x2 * 37; s1) Dim h2 As HashCodeExample = New HashCodeExample (x1 * 37; s2) …………………………………………………………Page 305…………………………………………………………… CH A PT E R 1 0 ■ L E A R N I N G A B O U T P E R S IS T E N CE 283 Dim ht As Hashtable = New Hashtable() ht。Add(h1; Nothing) ht。Add(h2; Nothing) This shows that having two objects with pletely different states results in the same hash…code value and generates an exception because Equals() has been implemented incor rectly。 In the implementation of Hashtable; when an added object collides with another already existing object; an equality test is made。 If the equality test returns True; then the exception is generated because Hashtable does not allow you to add an object with the same state as another object。 The solution is not to fix the GetHashCode() method; but rather to modify the Equals() method: Public Overrides Function Equals(ByVal obj As Object) As Boolean If TypeOf (obj) Is HashcodeExample Then If obj。GetHashCode() Me。GetHashCode() Then Return False End If Dim toTest As HashcodeExample = DirectCast(obj; HashcodeExample) If toTest。value = Me。value Then If toTest。buffer = Me。buffer Then Return True End If End If End If Return False End Function The logic of the modified Equals() method is to first test if both types are identical。 If not; then False is returned。 Next; test if GetHashCode() returns unequal values。 GetHashCode() will always return different values for objects that have different data members。 If the hash…code values are equal; then es the hard work of individually testing each data member for equality。 The hard work is delegated as the last step; because any object that reaches that point will probably be identical; but you need to be 100% certain。 The Important Stuff to Remember In this chapter; you learned how to process a stream of data using the console。 Here are the main items to remember: o When data is moved from one medium to another; it is streamed。 o There are two major types of streams: text and binary。 o Text streams are universal and can be read by all puters。 …………………………………………………………Page 306…………………………………………………………… 284 CH AP T E R 1 0 ■ L E A R N I N G A B OU T P E R S IS TE N CE o Binary streams are specific to the program and sometimes to the processor。 Imagine the situation of having to decipher a C++ data stream generated by a PowerPC chip。 Most likely; the numbers that you read will be wrong because of the way that Intel or AMD chips store their numbers。 Generally speaking; with binary streams; you will be conversing with two implementations。 If not; use text streams。 o When streaming data; it is best to customize as little as poss