嗔秤戻幣�哉膵�云利匈嬉蝕湊蛸賜�塋床四衲���萩晦編報炎嘔囚^泡仟 ̄云利匈��
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
酔楯荷恬: 梓囚徒貧圭�鮗� ○ 賜 ★ 辛酔堀貧和鍬匈 梓囚徒貧議 Enter 囚辛指欺云慕朕村匈 梓囚徒貧圭�鮗� ● 辛指欺云匈競何!
梁椣戻幣�� 梁心弌傍議揖扮窟燕得胎��傍竃徭失議心隈才凪万弌誌育断蛍�輌臆惨軼僑〃�燕慕得珊辛參資誼持蛍才将刮襲潜��範寔亟圻幹慕得 瓜寡追葎娼得辛參資誼寄楚署衛、持蛍才将刮襲潜填��