异常处理

异常处理

Exception 类

System 单元中的 Exception 类,直接继承自 TObject 类:

1
2
3
4
5
6
Exception = class(TObject)
private
FMessage: string;
FHelpContext: Integer;
...//其它成员省略
end;
  • FMessage 用于异常产生的信息
  • FHelpContext 用于描述异常的唯一标识符我们可

可以从这个类派生我们自己的异常类,习惯上异常类以大写字母 E 开头。

SysUtils 单元中定义了一些常见的异常类。基本上,这些异常类涵盖我们日常编程所能遇到的绝大部分异常。

try...except...end 语句

Try...except... 专用于处理各类异常。

其形式为:

1
2
3
4
5
6
7
8
9
try
语句区1
except
语句区2
[
else
语句区3
]
end;
  • 执行 “语句区1”,如果一切正常不发生异常,则跑到 end 之后的一条语句
  • 如果发生异常,则跳出 “语句区1”,绕开 “语句区1” 后面未执行的语句会,跳到 “语句区2
  • “语句区2” 寻找匹配的异常类型,并执行
  • 如果在 “语句区2” 找不到匹配的异常类型,则跳到 else 的 “语句区3” 执行(如果有 else 的话)
  • 如果不存在 else 的部分,又找不到匹配的异常类型,则会将异常抛出给上一层 try

上述 except 的排列格式如下:

1
2
3
4
5
6
7
8
9
10
except
on ExceptionType1 do
异常处理1
on ExceptionType2 do
异常处理2
on ExceptionType3 do
异常处理3
...
on ExceptionTypeN do
异常处理N

举例:

1
2
3
4
5
6
7
8
9
10
try
raise Exception.Create('error');
except
on TObject do
ShowMessage('TObject type');
on T1 do
ShowMessage('T1 type');
else
ShowMessage('else');
end;

上述例子中,异常会被捕获,执行到 TObject 类型的区块中。因为抛出的异常是 Exception 类型,Exception 继承自 TObject,所以第一个异常处理的类型匹配就符合条件。

except 区也可以不需要 on 来类型匹配:

例如:

1
2
3
4
5
6
try
Result := A div B;
Inc (Result);
except
Result := 0;
end;

上面例子是,发生异常时,不管什么类型的异常,都可以跑到 except 区,进行补救工作。

except 区可以声明异常类型的变量,例如:

1
2
3
4
5
6
try
raise Exception.Create('error');
except
on ex: Exception do // ex为变量名
ShowMessage (ex.Message);
end

try...finally...end 语句

Try...finally... 用于处理不管有没有发生异常,都进行收尾工作

其形式为:

1
2
3
4
5
try
语句区1
finally
语句区2
end;
  • 执行 “语句区1”,如果一切正常不发生异常,则跑到 finally 之后的 “语句区2 第一条语句
  • 如果发生异常,则跳出 “语句区1”,绕开 “语句区1” 后面未执行的语句会,跳到 finally“语句区2

手动抛出异常

使用 raise 关键字可以手动抛出异常。raise 单独作为一条语句,后面带一个表示异常的对象:

1
2
3
raise obj;
//
raise Exception.Create('error');

Abort 语句

系统提供了 Abort 过程,它可以在内部自动创建了一个 EAbort 异常类的对象并提交给上一层的异常处理语句。

EAbort 直接继承于 Exception,它被称为静默异常类,因为程序在引发此类的异常时不会显示任何对话框来提示用户。

换而言之, EAbort 类的异常在引发时不会对程序有任何干扰。在需要使用 raise 手动触发一个 EAbort 类的异常时可直接使用 Abort 语句代替

exceptfinally 共存

try 后只能跟 except 或者 finally,两者不能共存在同一个 try 块中。

如果实际应用中需要 except 或者 finally 共存的话,可以采用两个 try 语句块来实现:

1
2
3
4
5
6
7
8
9
try
try
//
except
//
end;
finally
//
end;