概要:
本文承接上一篇名为“非结构化异常处理--具有非结构化异常处理的计算器”的博客。本文将计算器的代码用VB.NET语句写一个具有结构化异常处理的简单计算器,主要介绍VB.NET中的结构化异常处理的知识。
确定按钮的代码:
Private Sub Button16_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button16.Click Dim r As Decimal '保存计算结果的变量 Dim t As String = TextBox1.Text '用于保存文本框中的算术表达式 Try Dim space As Integer = t.IndexOf(" ") '搜索空格位置,如果没有空格,返回值为0 '字符串的取子符方法,第二个参数小于0,则将产生的错误号为5的异常 Dim s1 As String = t.Substring(0, space) '通过取子串的方法获得第一个运算数 Dim op As String = t.Substring(space + 1, 1) '通过取字串方法获得运算符 Dim s2 As String = t.Substring(space + 3) '通过取子串的方法获得第二个运算数 Dim arg1, arg2 As Integer arg1 = Convert.ToInt32(s1) : arg2 = Convert.ToInt32(s2) Select Case op Case "+" : r = arg1 + arg2 Case "-" : r = arg1 - arg2 Case "*" : r = arg1 * arg2 Case "/" : r = arg1 / arg2 Case Else MsgBox("输入的运算符有误!") Exit Sub End Select TextBox1.Text = CStr(r) '显示结果 Exit Sub Catch Exam As System.OverflowException '算术溢出异常处理 MsgBox("算术运算溢出", , "溢出提示") Catch Exam As System.ArgumentException '参数数目不够或值不在范围内异常处理 MsgBox("参数有误,应输入运算符和第二个运算数!", , "参数有误提示") Catch Exam As System.FormatException '参数格式不正确异常处理 MsgBox("字符串中出现了非数字字符", , "参数格式不正确提示") Catch Exam As SystemException '其他异常处理 MsgBox("其他异常,错误号为:" & Err.Number & Chr(10) & Chr(13) & "错误提示:" & Err.Description) End Try End Sub
程序中的语句“Try…Catch…Finally…End Try”是专门用于结构化异常处理的语句。
结构化异常处理能帮助程序员创建和维护具有可靠,全面的错误处理程序的项目。在结构化异常处理中,代码块是封装的,每个块有一个或几个关联的处理程序。每个处理程序对它处理的异常类型指定某种形式的筛选条件。当受保护的代码块内的代码引发异常时,按顺序搜索相应的异常处理集,并执行第一个与筛选条件匹配的处理程序。“Try…Catch…Finally…EndTry”语句用于处理给定代码段中可能出现的某些或所有错误,而同时代码仍保持运行。该语句的格式与功能如下:
格式:
Try
Try语句块 ‘该语句块可能会引发异常
[Catch [exception [As type]] [When expression] ‘用于捕获Try语句中的异常
Catch] ‘Catch语句块用来对捕获的错误进行处理
………….
[Finally
[finally语句块]] ‘Finally语句块,存放异常处理后执行的代码
End Try
功能:
执行“Try语句块”中的语句,如果产生异常,则系统自动查找离可以处理这个异常最近的Catch语句,并且在运行时决定异常类型。首先,会寻找包含此代码的Try块。当找到Try块时,系统将从与此Try块相关联的一个或多个Catch块中,寻找一个符合条件的块执行。这个查找一个进行直到找到可以处理当前的异常的Catch为止。找到异常处理块后,将执行其中的处理代码,在处理代码中进行异常处理或重新抛出异常。无论是否有异常发生,均会执行Finally块中的“语句组n+1”。
说明:
1.[exception [As type]] 用来指定捕获指定类型或其派生类型的异常。例如,若此项为“Ex AS DivideByZeroException”,则在执行Try块时发生了整数除数为0的异常,将执行该Catch语句块。
2. [When expression] 用来指定执行该Catch语句块必须满足的条件,通常要根据Err对象中的某些信息构成表达式。例如,若此项为“Where Err.Number=6”,则在执行Try块时发生了数据溢出异常,将执行该Catch语句块。
3. 执行Try块语句发生异常时,将从第一个Catch块开始寻找匹配的异常,找到第一个匹配的异常时,执行其中的Catch语句块。执行过后,如果有Finally语句块则执行该语句块,如果没有那么跳出Try语句。
4.可以省略Catch块。由于没有Catch块,程序执行过程中发生异常,如果有Finally块则将直接执行该块中的代码,否则将直接中断。
5.可以省略Finally块。但是Catch和Finally块不能同时省略。
代码解释:
1. 一般处理异常时,使用若干个Catch块把感兴趣的异常处理完,再用一个Catch块,处理剩余的其他异常,此时Catch块中的变量应是“System.Exception”类的变量,因此所有的异常由该类派生。
2. 可以通过不带参数的Catch来捕获Try块中的所有异常。程序中的语句“Catch ExamAsSystemException”,可以直接写成“Catch”,效果是一样的。
3. 在Catch语句中列举类型时,要先列举在异常集成体系结构中最具体的类型,最后才列举System.Exception。如果在上例中我们将“
System.ArgumentException”类的异常放在“System.Exception”后面,提示信息将为“发生了其他异常”,原因是执行了第一个匹配的Catch语句块
归纳说明:
除了非结构化异常处理外,VB.NET还支持结构化异常处理,使用的语句时“Try…Catch…Finally…End Try”语句,从而使VB.NET,C++与C#等语言并列起来。编写结构化异常处理程序时,一个原则是:在Catch语句中列举异常类型时,要先列举在异常继承体系结构中最具体的类型,最后才列举System.Exception。