以下列代码作为示例:
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;
如果//做某些部分发生错误,则我假设创建的TSomeObject将不会被释放,并且Screen.Cursor仍然会被卡住为“小时玻璃”,因为代码在进入这些行之前已经被破坏了?
现在,除非我错误,否则应该有一个异常声明来处理任何这样的错误,例如:
procedure TForm1.Button1Click(Sender: TObject); var Obj: TSomeObject; begin try Screen.Cursor:= crHourGlass; Obj:= TSomeObject.Create; try // do something finally Obj.Free; end; Screen.Cursor:= crDefault; except on E: Exception do begin Obj.Free; Screen.Cursor:= crDefault; ShowMessage('There was an error: ' + E.Message); end; end;
现在,除非我做的事情真的很笨,所以在“最后”块和之后以及“异常”块中都不应该有相同的代码两次。
基本上我有时会有一些程序,可能类似于我发布的第一个样本,如果我得到一个错误,光标被卡住为小时玻璃。添加异常处理程序帮助,但它似乎是一种肮脏的方法 – 它基本上忽略了Finally块,更不用说从最终到异常部分的复制粘贴的丑陋的代码。
我仍然非常学习德尔福,如果这似乎是一个直接的问题/答案,那么道歉。
解决方法
你只需要两个try / finally块:
Screen.Cursor:= crHourGlass; try Obj:= TSomeObject.Create; try // do something finally Obj.Free; end; finally Screen.Cursor:= crDefault; end;
遵循的准则是最终应该使用,而不是除了保护资源。如你所观察到的,如果你尝试这样做,除此之外你被迫写入最终化代码两次。
一旦进入try / finally块,最后一节的代码就可以保证运行,无论try和finally之间发生什么。
所以,在上面的代码中,外部try / finally确保在任何异常情况下还原了Screen.Cursor。同样,内部try / finally确保在其生命周期中出现任何异常的情况下,Obj被破坏。
如果要处理异常,则需要一个独特的try / except块。但是,在大多数情况下,您不应尝试处理异常。只需让它传播到主应用程序异常处理程序,该处理程序将向用户显示一条消息。