Try…Except 结构是这样工作的:
Try后面到Except之前的语句通常是希望正常执行的代码,
在执行过程中如果触发了异常,程序就跳入Except部分。
在Except部分做出的处理可以有以下三种类型:
不需要确切知道异常的类型,只需要做笼统的处理时,
可以弹出一个警告信息框,或者释放已分配的资源,或者退出程序。程序示例如下:
Procedure TForm1.Button1Click(Sender :TObject)
Var
Num: Integer;
Begin
Try
Num:=StrToInt(Edit1.Text);
Edit2.Text:=IntToStr(Num*Num);
Except
ShowMessage(Edit1.Text+‘无法转成整数!’);
End;
End;
该例中,点击Button1后,
程序试图将编辑框Edit1中的内容转换为整型数,
整数平方之后再转换成字符串类型数据,在编辑框Edit2中显示。
如果Edit1.Text是7.89,传递给StrToInt将产生EConvertError异常,
因为7.89不是一个有效整数。异常产生后,将显示一条警告信息,并退出该过程。
利用异常处理句柄处理某个特定的异常
例如,在例1中可以针对EConvertError异常做出如下的处理:
Procedure TForm1.Button1Click(Sender :TObject)
Var
Num: Integer;
Begin
Try
Num:=StrToInt(Edit1.Text);
Edit2.Text:=IntToStr(Num*Num);
Except
On EConvertError Do ShowMessage(Edit1.Text+‘无法转成整数!’);
End;
End;
利用异常处理句柄处理多种异常
通常,执行的代码不只产生一种异常,
这就需要在Except部分进行更具体的测试,
根据产生的异常类型分别做出处理。现将例2稍加改动如下:
Procedure TForm1.Button1Click(Sender :TObject)
Var
Num: Integer;
Begin
Try
Num:=StrToInt(Edit1.Text);
Edit2.Text:=IntToStr(30 div Num);
Except
On EConvertError Do ShowMessage(Edit1.Text+‘无法转成整数!’);
On EDivByZero Do
Begin
ShowMessage(‘除数不能为零!’);
Edit2.Text:=’0’;
End;
End;
End;
在例3中,Try部分的第一条语句可能产生EConvertError 异常;
当 Num为零时,Try 部分的第二条语句还会产生被零除的异常(即产生EDivByZero 异常)。
由于产生异常原因不同,需要分别进行不同的处理。
例3中的Except 部分的代码也可以写成以下的形式,这两种异常处理的结果是一样的。
Except
On E:Exception Do
Begin
If E is EconvertErro Then ShowMessage(Edit1.Text+‘无法转成整数!’);
If E is EdivByZero Then
Begin
ShowMessage(‘除数不能为零!’);
Edit2.Text:=’0’;
End;
End;
Try…Finally 结构
Try…Finally 结构最大的用处是在异常发生的情况下,
确保释放应用程序已经分配的资源,或者完成一些必须的操作,
比如:剪贴板Clipboard 在打开之后必须调用Close 方法将剪贴板关闭;
数据感知组件更新禁止之后必须调用EnableControls方法才能使更新显示有效等。
Try…Finally 结构之所以能做到这一点,是因为不管异常是否发生,
程序都要执行Finally 部分。请看下面的例子:
Procedure TForm1.Button1Click(Sender :TObject)
Var
Icon : TIcon;
Begin
Try
Icon:=TIcon.Create;
Icon.LoadFromFile(‘Spin.ico’);
ImageList1.ReplaceIcon(0,Icon);
Finally
Icon.Free;
End;
End;
在例4中,Try 部分代码是从磁盘获取一个图标,
用来代替ImageList1 中的0号图标。
如果图标文件Spin.ico 不存在或者被损坏,
将会产生EFOpenError 异常,中断 Try 部分代码的执行,
但是程序会执行Finally 部分的代码,使得Icon 占用的资源
得以释放。
当然,如果没有发生任何异常,Finally 部分也将被执行。
可以说,Finally 部分是 Try…Finally 结构的“必经之路”。
Try…Except 与Try…Finally 的嵌套结构
Try…Finally 结构确实有它独到的功能,
但是Try…Finally结构中没有 Try…Except 结构中的异常处理句柄,
也就无法知道当前确切的异常类型,并且不论异常是否发生,
程序都执行 Finally 部分,
这就决定了 Try…Finally 结构无法对发生的异常进行特别的处理。
如果在应用程序中,既需要完成一些必要的操作,又要对发生的异常进行处理,
那么最好使用这两种结构的嵌套。请看下例:
Procedure TForm1.Button1Click(Sender :TObject)
var
Icon : TIcon;
Begin
Try
Try
Icon:=TIcon.Create;
Icon.LoadFromFile(‘Spin.ico’);
ImageList1.ReplaceIcon(0,Icon);
Finally
Icon.Free;
End;
Except
On EFOpenError Do ShowMessage(‘无法打开图标文件Spin.ico’);
End;
End;
在例5中,无论异常发生与否,都将执行Finally 部分释放图标占用的资源。
一旦异常发生,则产生警告信息。
上例是在 Try…Except 结构的 Try 部分嵌套 Try…Finally 结构,
也可以在 Try…Finally 结构的 Try 部分嵌套 Try…Except 结构,
前者是先执行必须的操作,再进行异常的处理,而后者是先进行异常的处理,
再执行必须的操作。在多数情况下,两者的区别并不大。
除此之外,Try…Except 结构和Try…Finally 结构还可以各自嵌套。
在复杂的应用程序中,
Except 部分或Finally部分的异常处理代码本身又有可能触发异常,
这就需要采用嵌套结构编写更深一层的异常处理代码,这里就不再详细举例了。