RE:How to correctly write Try..Finally..Except statements?
我仍然对OP的原始问题感到困惑。具体来说,该过程的最后一行(在try..finally..end之外)读取“Screen.Cursor:= crDefault”。
我的理解是try1.except | finally..end块中引发的任何异常将在
procedure TForm1.Button1Click(Sender: TObject);
var
Obj: TSomeObject;
begin
Screen.Cursor := crHourGlass;
Obj := TSomeObject.Create;
try
// do something
finally
Obj.Free;
end;
Screen.Cursor := crDefault;
end;
在上面的例子中,我没有看到为什么“Screen.Cursor:= crDefault”不会被执行的任何原因。如果我错了,请纠正我。
作为另一个例子,我编译了这一小段代码以帮助说明。运行代码时,将显示三(3)个ShowMessage()对话框。第一个“异常提升”,第二个“最后”和第三个“结束”。
procedure TForm1.Button1Click(Sender: TObject);
begin
try
try
showMessage(format('%s', [12]));
except
showMessage('Exception raised');
end;
finally
showMessage('finally');
end;
showMessage('at end');
end;
所以,我很困惑为什么他的“Screen.Cursor:= crDefault”没有被运行,原因是它的原始形式和代码。有人可以详细说明吗?
答案 0 :(得分:11)
您发布的代码似乎工作正常,因为您能够处理所有可能性。尝试稍微改一下,这样就会出现代码无法处理的异常:
procedure TForm1.Button1Click(Sender: TObject);
begin
try
try
raise Exception.Create('42');
except
on E: EDivByZero do
ShowMessage('DivByZero');
end;
finally
ShowMessage('Finally');
end;
ShowMessage('Got here');
end;
运行此功能,您将看到Finally
,然后是42
的例外,但没有Got here
消息。这是因为异常将您从当前块中取出,堆栈被解除,并且从最终的end
到过程结束的代码永远不会执行。
将最终的ShowMessage
来电从finally
移到procedure TForm1.Button1Click(Sender: TObject);
begin
try
try
raise Exception.Create('42');
except
on E: EDivByZero do
ShowMessage('DivByZero');
end;
finally
ShowMessage('Finally');
ShowMessage('Got here');
end;
ShowMessage('Will never get here');
end;
内,然后重新开始。
ShowMessage
您现在可以看到finally
块中的finally
,一个接一个,但不是end;
块finally
之后的一个。保证try..except
块内的代码可以执行,而超出它的代码可能会也可能不会。
为了更清楚,可以删除procedure TForm1.Button1Click(Sender: TObject);
begin
try
raise Exception.Create('42');
finally
ShowMessage('Finally');
ShowMessage('Got here');
end;
ShowMessage('Will never get here');
end;
块的存在:
try..finally
finally
块的整个目的是确保{{1}}部分内的代码在程序结束之前执行。
答案 1 :(得分:1)
你实际上没有捕获异常。在这种情况下,在异常时,将执行“finally”代码块,然后异常将展开堆栈。
答案 2 :(得分:1)
在Delphi中,finally
块并不真正处理try
块中发生的异常。它只保证始终执行finally
块中的代码,无论try
块中是否发生异常。如果在那里发生异常,它就不会被抓住。当一个异常没有被捕获时,你知道它下面的代码发生了什么。
要捕获可能发生的异常,请改用try...except...
块。您可以将这两个结构组合起来做这两个动作:(1)保证执行某些代码,以及(2)捕获可能发生的异常。常见的用法是这样的:
try
try
// do something that might cause an exception.
finally
// do something that must be executed WHATEVER happened.
end;
except
// do something ONLY IF an exception has occured.
end;
因此,您应该更改代码并移动Screen.Cursor := crDefault;
块中的finally
。此外,添加try...except...
块以包围try...finally...
块。像这样:
procedure TForm1.Button1Click(Sender: TObject);
var
Obj: TSomeObject;
begin
Screen.Cursor := crHourGlass;
Obj := TSomeObject.Create;
try
try
// do something.
finally
Obj.Free;
Screen.Cursor := crDefault;
end;
except
ShowMessage('An error has occured!');
end;
end;
或者,如果您不确定代码Obj := TSomeObject.Create;
是否足够安全,则应添加第二个try...finally...
块以包围它,如下所示:
procedure TForm1.Button1Click(Sender: TObject);
var
Obj: TSomeObject;
begin
Screen.Cursor := crHourGlass;
try
try
Obj := TSomeObject.Create;
try
// do something.
finally
Obj.Free;
end;
finally
Screen.Cursor := crDefault;
end;
except
ShowMessage('An error has occured!');
end;
end;
在那里,希望它有所帮助:)