RE:
How to correctly write Try..Finally..Except statements?
我仍然对OP的原始问题感到困惑.具体来说,该过程的最后一行(在try..finally..end之外)读取“Screen.Cursor:= crDefault”.
我的理解是try1.except | finally..end块中引发的任何异常将在“try”的“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()对话框.第一个“Exception Raised”和第二个“finally”和第三个“结束”.
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”没有被运行,原来的形式和代码.有人可以详细说明吗?
解决方法
您发布的代码似乎工作正常,因为您能够处理所有可能性.尝试稍微改一下,以便引发异常,代码无法处理:
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;
运行这个,你会看到最后,然后是42
的例外,但没有得到这里的消息.这是因为异常将您从当前块中取出,堆栈被解除,并且从finally的末尾到过程结束的代码永远不会执行.
将最终的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;
您现在将看到在finally块中一个接一个地调用ShowMessage,而不是在finally块结束之后的那个调用; 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过程中的代码在过程结束之前执行.