12.3 異常響應
異常響應為開發者提供了一個按自己的需要進行異常處理的機制。try …except …end形成了一個異常響應保護塊。與finally不同的是:正常情況下except 后面的語句并不被執行,而當異常發生時程序自動跳到except,進入異常響應處理模塊。當異常被響應后異常類自動清除。
下面的例子表示了文件打開、刪除過程中發生異常時的處理情況:
uses Dialogs;
var
F: Textfile;
begin
OpenDialog1.Title := 'Delete File';
if OpenDialog1.Execute then
begin
AssignFile(F, OpenDialog1.FileName);
try
Reset(F);
if MessageDlg('Erase ' +OpenDialog1.FileName + '?',
mtConfirmation, [mbYes, mbNo], 0) = mrYes then
begin
System.CloseFile(F);
Erase(F);
end;
except
on EInOutError do
MessageDlg('File I/O error.', mtError, [mbOk], 0);
on EAccessDenied do
MessageDlg('File access denied.', mtError, [mbOk], 0);
end;
end;
end.
保留字on…do用于判斷異常類型。必須注意的是:except后面的語句必須包含在某一個on…do模塊中,而不能單獨存在。這又是同finally不同的一個地方。
12.3.1 使用異常實例
上面所使用的異常響應方法可總結為如下的形式:
on ExceptionType do
{響應某一類的異常}
這種方法唯一使用的信息是異常的類型。一般情況下這已能滿足我們的需要。但我們卻無法獲取異常實例中包含的信息,比如異常消息、錯誤代碼等。假設我們需要對它們進行處理,那么就必須使用異常實例。
為了使用異常實例,需要為特定響應模塊提供一個臨時變量來保存它:
on EInstance : ExceptionType do …
在當前響應模塊中我們可以象使用一個普通對象那樣來引用它的數據成員。但在當前響應模塊之外不被承認。
下面的代碼用于獲取異常消息并按自己的方式顯示它:
{窗口中包括一個ScrollBar部件,一個Button部件}
procedure TErrorForm.Button1Click(Sender: TObject);
begin
try
ScrollBar1.Max := ScrollBar1.Min-1;
except
on E: EInvalidOperation do
MessageDlg('Ignoring Exception:'+E.Message,
mtInformation,[mbOK],0);
end;
end;
12.3.2 提供缺省響應
在異常響應模塊中,一般我們只對希望響應的特定異常進行處理。如果一個異常發生而響應模塊并沒有包含對它的處理代碼,則退出當前響應模塊,異常類仍被保留。
為了保證任何異常發生后都能在當前響應模塊中被清除,可以定義缺省響應:
try
{程序正常功能}
except
on ESomething do
{響應特定異常}
else
{提供缺省響應}
end;
由于else可以響應任何異常,包括我們一無所知的異常,因此在缺省響應中最好只包括諸如顯示一個消息框之類的處理,而不要改變程序的運行狀態或數據。
12.3.3 響應一族異常
諸如
on ExceptionType do
的異常響應語句不僅可響應本類異常,而且可以響應子類異常。對于象EIntError、EMathError等系統不會引發的異常,它們將只響應其子類異常。而對于象
on Exception do
這樣的語句將會對任何異常進行響應。
下面一段代碼對整數越界異常進行單獨處理,而對其它整數異常進行統一處理:
try
{整數運算}
except
on ERangeError do
{越界處理}
on EIntError do
{其它整數異常處理}
end;
由于異常在處理后即被清除,因而上面的代碼可保證不會使ERangeError異常被多次處理。假如顛倒兩條響應語句的順序,則ERangeError異常響應將永遠沒有被執行的機會。
由于異常在處理后即被清除,因而當希望對異常進行多次處理時就需要使用保留字raise來重引發一個當前異常。
下面的代碼同時使用了異常響應和異常保護。異常響應用于設置變量的值,異常保護用于釋放資源。當異常響應結束時利用raise重引發一個當前異常。
var
APointer: Pointer ;
AInt , ADiv: Integer;
begin
ADiv := 0;
GetMem ( APointer , 1024 );
try
try
AInt := 10 div ADiv ;
except
on EDivByZero do
begin
AInt := 0 ;
raise;
end;
end;
finally
FreeMem ( APointer , 1024 );
end;
end;
上面一段代碼體現了異常處理的嵌套。異常保護、異常響應可以單獨嵌套也可以如上例所示的那樣相互嵌套。 [1] [2] [3] 下一頁
|