嗔秤戻幣�哉膵�云利匈嬉蝕湊蛸賜�塋床四衲���萩晦編報炎嘔囚^泡仟 ̄云利匈��
源平慎弌傍利 卦指云慕朕村 紗秘慕禰 厘議慕尺 厘議慕禰 TXT畠云和墮 〆辺茄欺厘議箝誓匂〇

VB2008貫秘壇欺娼宥(PDF鯉塀哂猟井)-及54何蛍

酔楯荷恬: 梓囚徒貧圭�鮗� ○ 賜 ★ 辛酔堀貧和鍬匈 梓囚徒貧議 Enter 囚辛指欺云慕朕村匈 梓囚徒貧圭�鮗� ● 辛指欺云匈競何! 泌惚云慕短嗤堋響頼���誅卒亮茂�俊彭堋響��辛聞喘貧圭 "辺茄欺厘議箝誓匂" 孔嬬 才 "紗秘慕禰" 孔嬬��





              Public Sub New�┌� 

                  _constant = &H25 

                  _runningTotal = &H11 

              End Sub 



              Public Function AppendSuper��ByVal superHashCode As Integer�� As HashCodeAutomater 

                  _runningTotal = �┌�_runningTotal * _constant�� �� superHashCode�� 

                  Return Me 

              End Function 



              Public Function Append��ByVal obj As Object�� As HashCodeAutomater 

                  If ��obj Is Nothing�� Then 

                      Me。_runningTotal = ��Me。_runningTotal * Me。_constant�� 

                  ElseIf Not obj。GetType。IsArray Then 

                      Me。_runningTotal = �┌�Me。_runningTotal * Me。_constant�� �� obj。GetHashCode�� 

                  ElseIf TypeOf obj Is Long�┌� Then 

                      Me。Append��DirectCast��obj�察�Long�┌����� 

                  ElseIf TypeOf obj Is Integer�┌� Then 

                      Me。Append��DirectCast��obj�察�Integer�┌����� 

                  ElseIf TypeOf obj Is Short�┌� Then 

                      Me。Append��DirectCast��obj�察�Short�┌����� 

                  ElseIf TypeOf obj Is Char�┌� Then 

                      Me。Append��DirectCast��obj�察�Char�┌����� 


´´´´´´´´´´´´´´´´´´´´´´Page 303´´´´´´´´´´´´´´´´´´´´´´´

                                                     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 281 



        ElseIf TypeOf obj Is Byte�┌� Then 

            Me。Append��DirectCast��obj�察�Byte�┌����� 

        ElseIf TypeOf obj Is Double�┌� Then 

            Me。Append��DirectCast��obj�察�Double�┌����� 

        ElseIf TypeOf obj Is Single�┌� Then 

            Me。Append��DirectCast��obj�察�Single�┌����� 

        ElseIf TypeOf obj Is Boolean�┌� Then 

            Me。Append��DirectCast��obj�察�Boolean�┌����� 

        Else 

            Me。Append��DirectCast��obj�察�Object�┌����� 

        End If 

        Return Me 

    End Function 



    Public Function Append��ByVal array As Long�┌��� As HashCodeAutomater 

        If ��array Is Nothing�� Then 

            Me。_runningTotal = ��Me。_runningTotal * Me。_constant�� 

        Else 

            Dim i As Integer 

            For i = 0 To array。Length 1 

                Me。Append��array��i���� 

            Next i 

        End If 

        Return Me 

    End Function 



    Public Function Append��ByVal value As Long�� As HashCodeAutomater 

        Me。_runningTotal = _ 

            �┌�Me。_runningTotal * Me。_constant�� �� CInt�┌�value Xor ��value 〃〃 &H20�������� 

        Return Me 

    End Function 



    Public Function ToHashCode�┌� As Integer 

        Return _runningTotal 

    End Function 

End Class 



     The different implementations of the Append�┌� method belong to a single grouping for a  

single data type�察�Long。 For example�察�there is an Append�┌� method that accepts a  Long and a  Long  

array。 The full implementation of HashCodeAutomater would have an Append�┌� method for Short  

and Short array�察�and all the other data types。 There is no specific group implementation for the  

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 possible。 Doing so will pli

                   cate your program�察�and potentially introduce errors where none should exist。 



                o  It is important that you understand the concept of marshaling and the fact that each  

                   medium will have a different representation of the type。 A large part of your programming  

                   day will involve moving data from one stream to another。  



           Some Things for You to Do 



           The following are some exercises to apply what you learned in this chapter。 



                1。  In the implementation of TextProcessor�察�the display help routine was not very helpful。  

                    Fix the implementation。 



                2。  There were no testing routines for TextProcessor。 Devise some realistic tests。 By realistic  

                    tests�察�I mean tests that don¨t just focus on the class library and consider the application  

                    tested。 Focus on plete application tests。 



                3。  Having implemented the display help routine�察�think about whether or not the imple

                    mentation is correct。 The class Bootstrap is a general class that uses an  IProcessor  

                    instance�察�which means that different console applications will process different data。  

                    Thus�察�writing a general help output might work�察�but it will not help in resolving problems。  

                    Fix the console application TextProcessor and  ReaderWriter project so that the help  

                    message is both specific and general。 



                4。  In the Bootstrap class�察�when the output was redirected to a file ��as indicated by the  ´out  

                    argument���察�there was no check on whether or not the file exists。 Extend the Bootstrap  

                    class to include an additional mand´line argument that verifies if it is fine to overwrite  

                    the output file if it exists。 If an output file does exist and there is no explicit overwriting�察 �

                    generate an error and stop processing。 



                5。  The code in the final solution for IProcessor。Process�┌� has been identified as being hard  

                    to maintain because the code to check for duplicate dates is scattered throughout the  

                    method。 Rewrite the method implementation so that the code is logical and maintainable。 


´´´´´´´´´´´´´´´´´´´´´´Page 307´´´´´´´´´´´´´´´´´´´´´´´

C  H  A  P  T  E  R     1  1 



* * * 



Learning About  Generics 



Chapter 9 explained how to use lists�察�delegates�察�and lambda expressions。 In that chapter�察�you  

also saw an example of  generics when using lists to manage a collection of object instances。 

     The main focus of this chapter is  generics and how to use them in a black box context  

��the code doesn¨t know the specifics of the  generics parameter types��。 The secondary  

focus is an implementation of lambda expressions using a spreadsheet。 The idea is to get you  

well versed in  generics and lambda expressions�察�which you will likely use in your own  

production code�察�so that that there will be no surprises in your projects。  



Why Use  Generics�拭�



Here¨s a surprise for you�此�there is no imperative need for  generics�察�so you could skip this  

chapter and read the next one�察�right�拭�Wrong。 I could just as easily have said there is no need for  

Visual Basic properties�察�nor any other Visual Basic construct that enriches your programming  

abilities。 The reasons we have Visual Basic properties and  generics are programming  

elegance and expressiveness。 

     To understand what I am trying to get at�察�consider this sentence�此�



     Ducks walk flat feet quack loud 



     Reading the sentence�察�you get an idea of what is being said�察�but you are not pletely  

sure。 Visual Basic without  generics is like this sentence�察�in that you express your ideas in  

code�察�but some things are not as clear as you would like。 

     Visual Basic with  generics is like this sentence�此�



     Ducks walk in a funny manner due to their flat feet�察�and when they quack�察�it is very 

     loud。 



     The sentence is clearer and uses more words to describe the same thing。 The reason we  

talk using a more sophisticated language is that we want to explain concepts and be under

stood。 If you accept that�察�then you can accept why there is a need and context for  generics。  

And if not�察�feel free to skip this chapter and read the next one。  

     An example that illustrates how using  generics makes your code clearer�察�as well as  

more concise�察�than code that does not use  generics is a container。 A  container is a type  

that is used to manage other types�察�lists and collections are examples of containers。 To keep  



                                                                                                          285 


´´´´´´´´´´´´´´´´´´´´´´Page 308´´´´´´´´´´´´´´´´´´´´´´´

286       CH AP T E R   1 1   *    L E A R N I N G   A B OU T   。 N E T  G E N E R I CS 



          things simple�察�let¨s look at a container that manages a single reference。 The following is the less  

           concise version that uses the Object type。 



           Public Class Container  

              Private _managed As Object 



              Public Sub New��ByVal toManage As Object�� 

                  _managed = toManage 

              End Sub 



              Public ReadOnly Property Managed�┌� As Object 

                  Get 

                      Return _managed 

                  End Get 

              End Property 



           End Class 



                In the code�察�the class Container has a constructor with a parameter and a single property�察 �

          Managed�察�which references the variable _managed。 The idea 
卦指朕村 貧匯匈 和匯匈 指欺競何 壘��16�� 家��13��
酔楯荷恬: 梓囚徒貧圭�鮗� ○ 賜 ★ 辛酔堀貧和鍬匈 梓囚徒貧議 Enter 囚辛指欺云慕朕村匈 梓囚徒貧圭�鮗� ● 辛指欺云匈競何!
梁椣戻幣�� 梁心弌傍議揖扮窟燕得胎��傍竃徭失議心隈才凪万弌誌育断蛍�輌臆惨軼僑〃�燕慕得珊辛參資誼持蛍才将刮襲潜��範寔亟圻幹慕得 瓜寡追葎娼得辛參資誼寄楚署衛、持蛍才将刮襲潜填��