Author:水如烟
一、异常是避免不了的
异常是避免不了的。比如将一个八位数字字串转换为相应的日期。
初始的代码如下:
当接受的字串真是符合日期转换时,当然一切正常。
但是当字串不符合日期转换时,就发生异常了。
在这个类,能够避免预知的错误吗?能够利用Try...Catch...Finnaly吗?无论我怎么努力,我发现,无法避免,也不能使用Try...Catch。我就算告诉用户,你的输入错了,但我也无法输出合理的结果。能Return Nothing吗?不能!Nothing在DataTime里头就是0001年1月1日。为此,我只能什么都不处理,就让它异常好了。
二、异常真的不能避免吗
老天,我象是自打嘴巴了。
为了正常使用Dig8ToDateTime,我必须在用户界面上来检测输入是否合法。当我做到了这一步时,认为合法了,我发现,结果已经出来了,根本没有再使用Dig8ToDateTime这个类的必要。就是说,Dig8ToDateTime类毫无使用价值。
可我喜欢这个类,它在合法输入时带给我方便。现在,我变通一下,在输出结果前强制自检,不经自检,就不能使用Dig8ToDateTime.ToDateTime。
现在的代码如下:
用户(这里指编程者)在使用这个类,在不知其特殊用法的情况下,一般是这样写的:
在合法输入时,是正确的;不合法时,当然会发生异常:
三、尽早预防异常
如果事前知道输入非法,那就可以即时回头,告知用户。下面,我加强了对数字合理性的判别。
四、尽可能减少异常抛出时间
Dig8ToDateTime类内还是不能避开异常的发生。闰年的二月,每月的31,不好判断。是能判断,可要做到的话,那这个类真没价值了。我只好用Try...Catch来应付。真遇到这种的非法输入时,肯定会发生异常,只不过是将异常控制在Try块内。这里还有没有改进的地方?既然避免不了异常的抛出,能不能缩短抛出的时间?以下想法只是估测,实际不知有没有用。
当运行环境遇到异常时,NET会寻找异常的类型,在运行库的异常数组里找,找到匹配的了,才抛出这个异常。我想的是能不能缩短它寻找的时间。看了帮助文档,DateTime.Parse()抛出异常的类型是FormatException,我就用它来代替Exception。实际上有没有效果呢,我真不知道。
这个类,我现在只能做成这样了。最后发现,无论如何,异常还是免不了的。并且,我还主动的生成新的异常New ApplicationException。
最后是这样,将Value改成属性。
测试代码:
一、异常是避免不了的
异常是避免不了的。比如将一个八位数字字串转换为相应的日期。
初始的代码如下:
Public Class Dig8ToDateTime
Private Const DIG8_PATTERN As String = "\b(\d{4})(\d{2})(\d{2})\b"
Private Const DIG8_REPLACEMENT As String = "${1}-${2}-${3}"
'将8位数字转换为日期表示格式,如"20051025"转换为"2005-10-25"
Private Shared Function ToDateFormat(ByVal Value As String) As String
Return System.Text.RegularExpressions.Regex.Replace(Value, DIG8_PATTERN, DIG8_REPLACEMENT)
End Function
Public Shared Function ToDateTime(ByVal Value As String) As DateTime
Return DateTime.Parse(ToDateFormat(Value))
End Function
End Class
Private Const DIG8_PATTERN As String = "\b(\d{4})(\d{2})(\d{2})\b"
Private Const DIG8_REPLACEMENT As String = "${1}-${2}-${3}"
'将8位数字转换为日期表示格式,如"20051025"转换为"2005-10-25"
Private Shared Function ToDateFormat(ByVal Value As String) As String
Return System.Text.RegularExpressions.Regex.Replace(Value, DIG8_PATTERN, DIG8_REPLACEMENT)
End Function
Public Shared Function ToDateTime(ByVal Value As String) As DateTime
Return DateTime.Parse(ToDateFormat(Value))
End Function
End Class
当接受的字串真是符合日期转换时,当然一切正常。
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Console.WriteLine(Dig8ToDateTime.ToDateTime("20051031").ToLongDateString)
End Sub
'输出结果:2005年10月31日
Console.WriteLine(Dig8ToDateTime.ToDateTime("20051031").ToLongDateString)
End Sub
'输出结果:2005年10月31日
但是当字串不符合日期转换时,就发生异常了。
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Console.WriteLine(Dig8ToDateTime.ToDateTime("2005093").ToLongDateString)
End Sub
Console.WriteLine(Dig8ToDateTime.ToDateTime("2005093").ToLongDateString)
End Sub
在这个类,能够避免预知的错误吗?能够利用Try...Catch...Finnaly吗?无论我怎么努力,我发现,无法避免,也不能使用Try...Catch。我就算告诉用户,你的输入错了,但我也无法输出合理的结果。能Return Nothing吗?不能!Nothing在DataTime里头就是0001年1月1日。为此,我只能什么都不处理,就让它异常好了。
二、异常真的不能避免吗
老天,我象是自打嘴巴了。
为了正常使用Dig8ToDateTime,我必须在用户界面上来检测输入是否合法。当我做到了这一步时,认为合法了,我发现,结果已经出来了,根本没有再使用Dig8ToDateTime这个类的必要。就是说,Dig8ToDateTime类毫无使用价值。
可我喜欢这个类,它在合法输入时带给我方便。现在,我变通一下,在输出结果前强制自检,不经自检,就不能使用Dig8ToDateTime.ToDateTime。
现在的代码如下:
Public Class Dig8ToDateTime
Private Const DIG8_PATTERN As String = "\b(\d{4})(\d{2})(\d{2})\b"
Private Const DIG8_REPLACEMENT As String = "${1}-${2}-${3}"
Private Shared IsOK As Boolean
Private Shared Result As DateTime
'将8位数字转换为日期表示格式,如"20051025"转换为"2005-10-25"
Private Shared Function ToDateFormat(ByVal Value As String) As String
Return System.Text.RegularExpressions.Regex.Replace(Value, DIG8_PATTERN, DIG8_REPLACEMENT)
End Function
Public Shared Function CheckInput(ByVal Value As String) As Boolean
Try
Result = DateTime.Parse(ToDateFormat(Value))
IsOK = True
Catch ex As Exception
IsOK = False
End Try
Return IsOK
End Function
Public Shared Function Value() As DateTime
If Not IsOK Then
Throw New ApplicationException("请使用如下方法" & System.Environment.NewLine & _
"Dim t As DateTime" & System.Environment.NewLine & _
"If Dig8ToDateTime.CheckInput(""20051201"") Then " & System.Environment.NewLine & _
" t = Dig8ToDateTime.Value" & System.Environment.NewLine & _
"Else " & System.Environment.NewLine & _
" MsgBox(""输入错误"") " & System.Environment.NewLine & _
"End If")
End If
IsOK = False
Return Result
End Function
End Class
Private Const DIG8_PATTERN As String = "\b(\d{4})(\d{2})(\d{2})\b"
Private Const DIG8_REPLACEMENT As String = "${1}-${2}-${3}"
Private Shared IsOK As Boolean
Private Shared Result As DateTime
'将8位数字转换为日期表示格式,如"20051025"转换为"2005-10-25"
Private Shared Function ToDateFormat(ByVal Value As String) As String
Return System.Text.RegularExpressions.Regex.Replace(Value, DIG8_PATTERN, DIG8_REPLACEMENT)
End Function
Public Shared Function CheckInput(ByVal Value As String) As Boolean
Try
Result = DateTime.Parse(ToDateFormat(Value))
IsOK = True
Catch ex As Exception
IsOK = False
End Try
Return IsOK
End Function
Public Shared Function Value() As DateTime
If Not IsOK Then
Throw New ApplicationException("请使用如下方法" & System.Environment.NewLine & _
"Dim t As DateTime" & System.Environment.NewLine & _
"If Dig8ToDateTime.CheckInput(""20051201"") Then " & System.Environment.NewLine & _
" t = Dig8ToDateTime.Value" & System.Environment.NewLine & _
"Else " & System.Environment.NewLine & _
" MsgBox(""输入错误"") " & System.Environment.NewLine & _
"End If")
End If
IsOK = False
Return Result
End Function
End Class
用户(这里指编程者)在使用这个类,在不知其特殊用法的情况下,一般是这样写的:
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dig8ToDateTime.CheckInput("20050930")
Console.WriteLine(Dig8ToDateTime.Value.ToLongDateString)
End Sub
Dig8ToDateTime.CheckInput("20050930")
Console.WriteLine(Dig8ToDateTime.Value.ToLongDateString)
End Sub
在合法输入时,是正确的;不合法时,当然会发生异常:
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dig8ToDateTime.CheckInput("2005093")
Console.WriteLine(Dig8ToDateTime.Value.ToLongDateString)
End Sub
Dig8ToDateTime.CheckInput("2005093")
Console.WriteLine(Dig8ToDateTime.Value.ToLongDateString)
End Sub
于是会修改代码:
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
If Dig8ToDateTime.CheckInput("200509") Then
Console.WriteLine(Dig8ToDateTime.Value.ToLongDateString)
Else
MsgBox("输入错误")
End If
End Sub
If Dig8ToDateTime.CheckInput("200509") Then
Console.WriteLine(Dig8ToDateTime.Value.ToLongDateString)
Else
MsgBox("输入错误")
End If
End Sub
三、尽早预防异常
如果事前知道输入非法,那就可以即时回头,告知用户。下面,我加强了对数字合理性的判别。
Public Class Dig8ToDateTime
Private Const DIG8_PATTERN As String = "\b(0\d{2}[1-9]|[1-9]\d{3})(0[1-9]|1[0-2])(0[1-9]|[1|2]\d|3[0-1])\b"
Private Const DIG8_REPLACEMENT As String = "${1}-${2}-${3}"
Private Shared IsOK As Boolean
Private Shared Result As DateTime
'将8位数字转换为日期表示格式,如"20051025"转换为"2005-10-25"
Private Shared Function ToDateFormat(ByVal Value As String) As String
Return System.Text.RegularExpressions.Regex.Replace(Value, DIG8_PATTERN, DIG8_REPLACEMENT)
End Function
Public Shared Function CheckInput(ByVal Value As String) As Boolean
Dim f As String = ToDateFormat(Value)
If Not f.Length = 10 Then 'Return False
IsOK = False
Return IsOK
End If
Try
Result = DateTime.Parse(f)
IsOK = True
Catch ex As Exception
IsOK = False
End Try
Return IsOK
End Function
Public Shared Function Value() As DateTime
If Not IsOK Then
Throw New ApplicationException("请使用如下方法" & System.Environment.NewLine & _
"Dim t As DateTime" & System.Environment.NewLine & _
"If Dig8ToDateTime.CheckInput(""20051201"") Then " & System.Environment.NewLine & _
" t = Dig8ToDateTime.Value" & System.Environment.NewLine & _
"Else " & System.Environment.NewLine & _
" MsgBox(""输入错误"") " & System.Environment.NewLine & _
"End If")
End If
IsOK = False
Return Result
End Function
End Class
Private Const DIG8_PATTERN As String = "\b(0\d{2}[1-9]|[1-9]\d{3})(0[1-9]|1[0-2])(0[1-9]|[1|2]\d|3[0-1])\b"
Private Const DIG8_REPLACEMENT As String = "${1}-${2}-${3}"
Private Shared IsOK As Boolean
Private Shared Result As DateTime
'将8位数字转换为日期表示格式,如"20051025"转换为"2005-10-25"
Private Shared Function ToDateFormat(ByVal Value As String) As String
Return System.Text.RegularExpressions.Regex.Replace(Value, DIG8_PATTERN, DIG8_REPLACEMENT)
End Function
Public Shared Function CheckInput(ByVal Value As String) As Boolean
Dim f As String = ToDateFormat(Value)
If Not f.Length = 10 Then 'Return False
IsOK = False
Return IsOK
End If
Try
Result = DateTime.Parse(f)
IsOK = True
Catch ex As Exception
IsOK = False
End Try
Return IsOK
End Function
Public Shared Function Value() As DateTime
If Not IsOK Then
Throw New ApplicationException("请使用如下方法" & System.Environment.NewLine & _
"Dim t As DateTime" & System.Environment.NewLine & _
"If Dig8ToDateTime.CheckInput(""20051201"") Then " & System.Environment.NewLine & _
" t = Dig8ToDateTime.Value" & System.Environment.NewLine & _
"Else " & System.Environment.NewLine & _
" MsgBox(""输入错误"") " & System.Environment.NewLine & _
"End If")
End If
IsOK = False
Return Result
End Function
End Class
四、尽可能减少异常抛出时间
Dig8ToDateTime类内还是不能避开异常的发生。闰年的二月,每月的31,不好判断。是能判断,可要做到的话,那这个类真没价值了。我只好用Try...Catch来应付。真遇到这种的非法输入时,肯定会发生异常,只不过是将异常控制在Try块内。这里还有没有改进的地方?既然避免不了异常的抛出,能不能缩短抛出的时间?以下想法只是估测,实际不知有没有用。
当运行环境遇到异常时,NET会寻找异常的类型,在运行库的异常数组里找,找到匹配的了,才抛出这个异常。我想的是能不能缩短它寻找的时间。看了帮助文档,DateTime.Parse()抛出异常的类型是FormatException,我就用它来代替Exception。实际上有没有效果呢,我真不知道。
Public Class Dig8ToDateTime
Private Const DIG8_PATTERN As String = "\b(0\d{2}[1-9]|[1-9]\d{3})(0[1-9]|1[0-2])(0[1-9]|[1|2]\d|3[0-1])\b"
Private Const DIG8_REPLACEMENT As String = "${1}-${2}-${3}"
Private Shared IsOK As Boolean
Private Shared Result As DateTime
'将8位数字转换为日期表示格式,如"20051025"转换为"2005-10-25"
Private Shared Function ToDateFormat(ByVal Value As String) As String
Return System.Text.RegularExpressions.Regex.Replace(Value, DIG8_PATTERN, DIG8_REPLACEMENT)
End Function
Public Shared Function CheckInput(ByVal Value As String) As Boolean
Dim f As String = ToDateFormat(Value)
If Not f.Length = 10 Then 'Return False
IsOK = False
Return IsOK
End If
Try
Result = DateTime.Parse(f)
IsOK = True
Catch ex As FormatException
IsOK = False
End Try
Return IsOK
End Function
Public Shared Function Value() As DateTime
If Not IsOK Then
Throw New ApplicationException("请使用如下方法" & System.Environment.NewLine & _
"Dim t As DateTime" & System.Environment.NewLine & _
"If Dig8ToDateTime.CheckInput(""20051201"") Then " & System.Environment.NewLine & _
" t = Dig8ToDateTime.Value" & System.Environment.NewLine & _
"Else " & System.Environment.NewLine & _
" MsgBox(""输入错误"") " & System.Environment.NewLine & _
"End If")
End If
IsOK = False
Return Result
End Function
End Class
Private Const DIG8_PATTERN As String = "\b(0\d{2}[1-9]|[1-9]\d{3})(0[1-9]|1[0-2])(0[1-9]|[1|2]\d|3[0-1])\b"
Private Const DIG8_REPLACEMENT As String = "${1}-${2}-${3}"
Private Shared IsOK As Boolean
Private Shared Result As DateTime
'将8位数字转换为日期表示格式,如"20051025"转换为"2005-10-25"
Private Shared Function ToDateFormat(ByVal Value As String) As String
Return System.Text.RegularExpressions.Regex.Replace(Value, DIG8_PATTERN, DIG8_REPLACEMENT)
End Function
Public Shared Function CheckInput(ByVal Value As String) As Boolean
Dim f As String = ToDateFormat(Value)
If Not f.Length = 10 Then 'Return False
IsOK = False
Return IsOK
End If
Try
Result = DateTime.Parse(f)
IsOK = True
Catch ex As FormatException
IsOK = False
End Try
Return IsOK
End Function
Public Shared Function Value() As DateTime
If Not IsOK Then
Throw New ApplicationException("请使用如下方法" & System.Environment.NewLine & _
"Dim t As DateTime" & System.Environment.NewLine & _
"If Dig8ToDateTime.CheckInput(""20051201"") Then " & System.Environment.NewLine & _
" t = Dig8ToDateTime.Value" & System.Environment.NewLine & _
"Else " & System.Environment.NewLine & _
" MsgBox(""输入错误"") " & System.Environment.NewLine & _
"End If")
End If
IsOK = False
Return Result
End Function
End Class
这个类,我现在只能做成这样了。最后发现,无论如何,异常还是免不了的。并且,我还主动的生成新的异常New ApplicationException。
最后是这样,将Value改成属性。
''' -----------------------------------------------------------------------------
''' Project : LzmTW.Common
''' Class : Common.Dig8ToDateTime
'''
''' -----------------------------------------------------------------------------
''' <summary>
''' 将8位数字串转换为日期
''' </summary>
''' <remarks>
''' 请按 "IF CheckInput(Value) Then Else EndIf" 方式使用
''' </remarks>
''' <history>
''' [lzmtw] 2005-10-26 Created
''' </history>
''' -----------------------------------------------------------------------------
Public Class Dig8ToDateTime
'日期型数字匹配正则表达式
Private Const DIG8_PATTERN As String = "\b(0\d{2}[1-9]|[1-9]\d{3})(0[1-9]|1[0-2])(0[1-9]|[1|2]\d|3[0-1])\b"
Private Const DIG8_REPLACEMENT As String = "${1}-${2}-${3}"
Private Shared _IsOK As Boolean
Private Shared _Result As DateTime
Private Sub New()
End Sub
Private Shared Function ToDateFormat(ByVal Value As String) As String '将20051210转换为2005-12-10
Return System.Text.RegularExpressions.Regex.Replace(Value, DIG8_PATTERN, DIG8_REPLACEMENT)
End Function
''' -----------------------------------------------------------------------------
''' <summary>
''' 输入
''' </summary>
''' <param name="Value">8位数字串</param>
''' <returns></returns>
''' <remarks>
''' </remarks>
''' <history>
''' [lzmtw] 2005-10-26 Created
''' </history>
''' -----------------------------------------------------------------------------
Public Shared Function CheckInput(ByVal Value As String) As Boolean
Dim f As String = ToDateFormat(Value)
If Not f.Length = 10 Then
_IsOK = False
Return _IsOK
End If
Try
_Result = DateTime.Parse(f)
_IsOK = True
Catch ex As FormatException
_IsOK = False
End Try
Return _IsOK
End Function
''' -----------------------------------------------------------------------------
''' <summary>
''' 返回值
''' </summary>
''' <value></value>
''' <remarks>
''' 按 "IF CheckInput(Value) Then Else EndIf" 方式使用
''' </remarks>
''' <history>
''' [lzmtw] 2005-10-26 Created
''' </history>
''' -----------------------------------------------------------------------------
Public Shared ReadOnly Property Value() As DateTime
Get
If Not _IsOK Then
Throw New ApplicationException("请使用如下方法" & System.Environment.NewLine & _
"Dim t As DateTime" & System.Environment.NewLine & _
"If Dig8ToDateTime.CheckInput(""20051201"") Then " & System.Environment.NewLine & _
" t = Dig8ToDateTime.Value" & System.Environment.NewLine & _
"Else " & System.Environment.NewLine & _
" MsgBox(""输入错误"") " & System.Environment.NewLine & _
"End If")
End If
_IsOK = False
Return _Result
End Get
End Property
End Class
''' Project : LzmTW.Common
''' Class : Common.Dig8ToDateTime
'''
''' -----------------------------------------------------------------------------
''' <summary>
''' 将8位数字串转换为日期
''' </summary>
''' <remarks>
''' 请按 "IF CheckInput(Value) Then Else EndIf" 方式使用
''' </remarks>
''' <history>
''' [lzmtw] 2005-10-26 Created
''' </history>
''' -----------------------------------------------------------------------------
Public Class Dig8ToDateTime
'日期型数字匹配正则表达式
Private Const DIG8_PATTERN As String = "\b(0\d{2}[1-9]|[1-9]\d{3})(0[1-9]|1[0-2])(0[1-9]|[1|2]\d|3[0-1])\b"
Private Const DIG8_REPLACEMENT As String = "${1}-${2}-${3}"
Private Shared _IsOK As Boolean
Private Shared _Result As DateTime
Private Sub New()
End Sub
Private Shared Function ToDateFormat(ByVal Value As String) As String '将20051210转换为2005-12-10
Return System.Text.RegularExpressions.Regex.Replace(Value, DIG8_PATTERN, DIG8_REPLACEMENT)
End Function
''' -----------------------------------------------------------------------------
''' <summary>
''' 输入
''' </summary>
''' <param name="Value">8位数字串</param>
''' <returns></returns>
''' <remarks>
''' </remarks>
''' <history>
''' [lzmtw] 2005-10-26 Created
''' </history>
''' -----------------------------------------------------------------------------
Public Shared Function CheckInput(ByVal Value As String) As Boolean
Dim f As String = ToDateFormat(Value)
If Not f.Length = 10 Then
_IsOK = False
Return _IsOK
End If
Try
_Result = DateTime.Parse(f)
_IsOK = True
Catch ex As FormatException
_IsOK = False
End Try
Return _IsOK
End Function
''' -----------------------------------------------------------------------------
''' <summary>
''' 返回值
''' </summary>
''' <value></value>
''' <remarks>
''' 按 "IF CheckInput(Value) Then Else EndIf" 方式使用
''' </remarks>
''' <history>
''' [lzmtw] 2005-10-26 Created
''' </history>
''' -----------------------------------------------------------------------------
Public Shared ReadOnly Property Value() As DateTime
Get
If Not _IsOK Then
Throw New ApplicationException("请使用如下方法" & System.Environment.NewLine & _
"Dim t As DateTime" & System.Environment.NewLine & _
"If Dig8ToDateTime.CheckInput(""20051201"") Then " & System.Environment.NewLine & _
" t = Dig8ToDateTime.Value" & System.Environment.NewLine & _
"Else " & System.Environment.NewLine & _
" MsgBox(""输入错误"") " & System.Environment.NewLine & _
"End If")
End If
_IsOK = False
Return _Result
End Get
End Property
End Class
测试代码:
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim Dig8Converter As LzmTW.Common.Dig8ToDateTime
With Dig8Converter
If .CheckInput(Me.TextBox1.Text) Then
Me.TextBox2.Text = .Value.ToLongDateString
Else
Me.TextBox2.Text = "输入错误"
'如显示异常信息 Console.WriteLine(.Value)
End If
End With
End Sub
Dim Dig8Converter As LzmTW.Common.Dig8ToDateTime
With Dig8Converter
If .CheckInput(Me.TextBox1.Text) Then
Me.TextBox2.Text = .Value.ToLongDateString
Else
Me.TextBox2.Text = "输入错误"
'如显示异常信息 Console.WriteLine(.Value)
End If
End With
End Sub