梓囚徒貧圭�鮗� ○ 賜 ★ 辛酔堀貧和鍬匈��梓囚徒貧議 Enter 囚辛指欺云慕朕村匈��梓囚徒貧圭�鮗� ● 辛指欺云匈競何��
!!!!隆堋響頼��紗秘慕禰厮宴和肝写偬堋響��
Missing from the TestCallingExample�┌� method is an indication of whether the processing
worked。 It is assumed from the perspective of the caller of TestCallingExample�┌� that
calling TestCallingExample�┌� will always result in something being done。 The caller of
TestCallingExample�┌� has no way of knowing that something failed�察�other than if an exception
was thrown。
Code that tells you if something went wrong using an exception is both a blessing and a
curse。 It is a blessing because the code is telling you that something went wrong。 But it is a
curse because sometimes you know something could go wrong�察�and that it is OK�察�but you don¨t
want the exception to travel up the program hierarchy。 In these cases�察�you need to catch the
exception�察�which makes your code more plicated。
For example�察�say you wanted to parse a number。 The parsing routines tend to give a
result if everything worked OK�察�but generate an exception if things are not OK。 There is no
return value�察�just an exception。 But when parsing a number�察�you do know that things could go
wrong�察�so you will need to write an exception handler。 Following is some source code that
parses a number。
Function TestGetValue��ByVal buffer As String�� As Integer
Dim retval As Integer = 0
Try
retval = Integer。Parse��buffer��
Catch ex As FormatException
Console。WriteLine�─�Exception �──�& ex。Message & ;��;��
End Try
Return retval
End Function
In the example�察�the code realizes that if Parse�┌� is called and the string cannot be converted
into a number due to incorrect letters or numbers�察�an exception will be thrown。 The exception
will be caught�察�processed ��using the exception¨s Message property to obtain the problem���察�and
then the value of retval will be returned to the caller。 But what if an exception does happen�拭 �
The variable retval is initialized to a default value of 0�察�which is a valid formatted number and
can be interpreted as the result of a successful format processing。
´´´´´´´´´´´´´´´´´´´´´´Page 153´´´´´´´´´´´´´´´´´´´´´´´
CH AP T E R 5 * L E AR N IN G AB O U T V I SU A L B AS IC E X CE PT I ON HA N D L IN G 131
The problem in the code is that a developer is caught in a bind。 By capturing the exception�察 �
the method TestGetValue�┌� is saying�察 �I will always return to the caller a valid value。 ̄ Yet there
are instances when a valid value is not available。 In the case of parsing a number�察�an exception
is thrown。 So by capturing an exception�察�you are doing the pletely wrong thing�察�because
you should be letting the exception be caught by a higher´level caller。 But things can bee
sticky here。 Do you really want to inform the caller that a parse cannot occur�拭�Perhaps the caller
is more interested in whether a valid value is returned。 It¨s like saying to the CEO�察 �Oops�察�we
just ran out of staples。 ̄ Sure�察�staples might be important�察�and maybe the pany will not run
as smoothly�察�but do you really want to inform the CEO about every little problem�拭�
Microsoft developers know about this problem with parsing�察�and use an approach that
you can use as well。 As you learned in Chapter 3�察�there are two variations of parsing a number�此�
o Parse�┌� returns a valid number if the buffer could be parsed�察�and an exception if a
number could not be parsed。
o TryParse�┌� returns a True or False value indicating the result of the parse。
Here¨s how you could rewrite the TestGetValue�┌� method to use TryParse�┌��此�
Function TestGetValue��ByVal buffer As String�察�ByRef val As Integer�� As Boolean
Dim retval As Boolean = False
If Integer。TryParse��buffer�察�val�� Then
retval = True
End If
Return retval
End Function
In the modified example�察�TestGetValue�┌� returns a True or False to indicate a success or
failure when parsing a number。 If a True is returned�察�the parameter val will hold a valid number�察 �
otherwise�察�val should be not be used。
Some of you might have caught that my use of Parse�┌� and TryParse�┌� is not very creative。
The method TestGetValue�┌� could have been reduced to a single line�此�
Function TestGetValue��ByVal buffer As String�察�ByRef val As Integer�� As Boolean
Return Integer。TryParse��buffer�察�val��
End Function
Using Default State
Default state is a useful technique to guard against exceptions that developers often ignore。
When developers are writing their code�察�they will often return Nothing when things don¨t work
out。 Using Nothing is not a bad idea�察�but it adds unnecessary baggage。 For example�察�consider
the following code�此�
Class DefaultStateWrong
Private Function Tokenize��ByVal buffer As String�� As String�┌�
Return Nothing
End Function
´´´´´´´´´´´´´´´´´´´´´´Page 154´´´´´´´´´´´´´´´´´´´´´´´
132 CH AP T E R 5 * L E A R N IN G AB OU T V I SU A L B AS IC E X C E P TI ON H AN D L IN G
Public Sub IterateBuffers��ByVal buffer As String��
Dim found As String�┌� = Tokenize��buffer��
If found IsNot Nothing Then
For c1 As Integer = 0 To found。Length 1
Console。WriteLine�─�Found �──�& found��c1�� & ;��;��
Next
End If
End Sub
End Class
The problem in this example is Tokenize�┌��察�which is a method used to convert the param
eter buffer into a series of string tokens。 Using safe exception coding�察�if the data could not be
parsed�察�you could throw an exception�察�or you could return a Nothing value indicating that the
buffer could not be parsed。
The caller code knows that there is the possibility of a Nothing value when calling Tokenize�┌��察 �
and thus has an If test to check for the Nothing value。 The If test is defensive coding�察�but it also
adds plexity because you need to verify for a Nothing value。
What if Tokenize�┌� were a bit smarter and decided to return an empty array to indicate an
empty result set�拭�The logic of this is not incorrect�察�because the caller expects either a result set
with items or a result set with nothing in it。 If a dramatically bad parsing error has occurred�察�the
only recourse is to throw an exception。 Here is the rewritten code�此�
Class DefaultStateRight
Private Function Tokenize��ByVal buffer As String�� As String�┌�
Return New String�─�1�� �� ��
End Function
Public Sub IterateBuffers��ByVal buffer As String��
Dim found As String�┌� = Tokenize��buffer��
For c1 As Integer = 0 To found。Length 1
Console。WriteLine�─�Found �──�& found��c1�� & ;��;��
Next
End Sub
End Class
In the rewritten code�察�Tokenize�┌� returns an empty array that�察�when iterated using a For
loop�察�will cause zero iterations。 This is exception´safe code with improved readability。
But what happens if Tokenize�┌� does throw an exception�拭�With Tokenize�┌� throwing an
exception and the lack of a Try/Catch block in IterateBuffers�┌��察�it looks like IterateBuffers�┌�
is written incorrectly。 However�察�IterateBuffers�┌� is not written incorrectly�察�because Tokenize�┌�
will throw an exception only if something really problematic has occurred。 A