请看一个VB.NET结构化异常处理的例子。
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim i As Long, j As Long
j = 0
Try
i = 1 / j
Catch
MsgBox("ERROR")
Finally
MsgBox("Finally")
End Try
End Sub
当然,在实际编程中我们不会做仅仅弹出一个msgbox这么无聊的动作。Try 结构中
我们通常放一些可能引发异常的代码,这类的代码大多是访问文件(因为读写文件可能遇到被拒、磁盘满等情况)、访问注册表 等不可靠操作。当try结构中的代码执行出现异常时,程序直接跳转,执行catch结构中的代码,catch结构中,我们通常是放一些报告错误、处理错误的代码,比如用 Msgbox 报告给用户出了什么错,下一步用户该如何做等等信息。不论 是否发生异常,Finally结构中的代码是总是要执行的,因此我们可以在finally结构中放进去一些被称作“清理性代码”的语句,比如,关闭打开的文件、关闭打开的句炳、释放对象的实例等操作。
VB6是基于COM的开发语言,和c++中的栈上创建对象有很大的不同。VB6中的COM对象具有引用计数机制,这就意味着,在一个例程结束后,对象变量(指向对象实例的指针)会被自动销毁,那么对象实例的引用计数器的数值就会减一,如果计数器减到0,这个实例就会被系统自动销毁。而C++的栈上创建的对象则没有这种自我管理机制,它需要程序员显式的释放对象实例。(关于COM的原理,先说到这,以后专门详谈)。总之,对VB6来说,用结构化异常来保证对象实例的销毁并不是显得那么有用,但我们有足够的理由在VB6中使用结构化异常处理,显而易见,前面提到的那些情况:关闭打开的文件、关闭打开的各种句炳,这些都是使用结构化异常处理的理由。
VB6虽然没有直接提供结构化异常处理机制,但其实只要把 On Error 语句稍做变通就可以了。
请看VB6模拟出的结构化异常处理:
try: On Error GoTo catch
'{
在这里添加“不可靠代码”
'}
GoTo finally
catch:
'{
在这里添加“错误报告、错误处理代码”
'}
finally:
'{
在这里添加“清理性代码,比如:关闭文件、关闭句炳等”
'}
也许您可能持反对意见,告诉我这段代码用了 goto 语句,这是不好的编程风格。
不提倡用goto 是因为 滥用goto 会把代码变成“乱面条”,但很明显这段代码并没有
滥用goto ,而是非常谨慎了的用了一下 goto ,代码中的goto 全部整齐划一的指向
finally 语句。
如果您有“goto 洁癖”,那么只好试试这个了:
try: On Error GoTo catch
'{
在这里添加“不可靠代码”
'}
finally:
'{
在这里添加“清理性代码,比如:关闭文件、关闭句炳等”
Exit Sub
'}
catch:
'{
在这里添加“错误报告、错误处理代码”
Resume finally
'}
这种格式和前者是等效的,它没用goto,但我觉得它比前者更“面条”一些。^_^个人喜欢第一种。
后记:
1.注意:finally 中一定要放稳固的代码,如果finally中出了错,就会导致异常无法处理。
2.这种对结构化异常处理的模拟只是基本的模拟,与真正的结构化异常处理比起来,还是有差别的,比如真正的结构化异常处理是可以嵌套的,也就是说一个try..catch...finally结构中可以嵌入另一个try...catch...finally结构。
注意runtime errors 须将 On Error Goto 改为 On Error Resume Next 才能捕捉到错误。并做如下改动
调用方法
Try
conn.Open ConStr '可能出错的行[A]
endTry
sub try
On Error Resume Next
end sub
sub endTry
if Err.Number = 0 then
Catch
else
OK
end if
finally
end sub
sub catch
'这里对Err.Number进行判断,然后做相应处理
If Err.Number = XX then ....
On Error GoTo 0
end sub
sub OK
'这里是如果不出错应该继续执行的东西
On Error GoTo 0
end sub
sub finally
'这里是不论是否出错都可以执行的地方
end sub