将以下代码作为示例:
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;
如果
// do something
节中发生错误,我假定创建的TSomeObject将不会被释放,而Screen.Cursor仍将被卡为沙漏,因为在到达这些行之前代码已被破坏?现在,除非我犯错了,否则应该有一个Exception语句来处理这种错误的发生,例如:
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;
现在,除非我做的是真正愚蠢的事情,否则没有理由在Final块,之后块和Exception块中两次使用相同的代码。
基本上,我有时会执行某些步骤,这些步骤可能与我发布的第一个示例类似,并且如果遇到错误,光标将被卡为“沙漏”。添加Exception处理程序会有所帮助,但这似乎是一种肮脏的方式-它基本上忽略了finally块,更不用说从Final到Exception部分复制粘贴的丑陋代码了。
如果这似乎是一个直接的问题/答案,我仍然非常学习Delphi的道歉。
应该如何正确编写代码以处理语句并正确释放对象并捕获错误等?
最佳答案
您只需要两个try/finally
块:
Screen.Cursor:= crHourGlass;
try
Obj:= TSomeObject.Create;
try
// do something
finally
Obj.Free;
end;
finally
Screen.Cursor:= crDefault;
end;
遵循的准则是您应该使用
finally
而不是except
来保护资源。如您所见,如果尝试使用except
进行操作,那么您将不得不编写两次终结代码。进入
try/finally
块后,无论finally
和try
之间发生什么情况,finally
部分中的代码都可以运行。因此,在上面的代码中,外部
try/finally
确保在遇到任何异常时恢复Screen.Cursor
。同样,内部try/finally
可确保Obj
在其生存期内引发任何异常的情况下被销毁。如果要处理异常,则需要一个独特的
try/except
块。但是,在大多数情况下,您不应尝试尝试处理异常,而不要尝试。只需让它传播到主应用程序异常处理程序,该处理程序将向用户显示一条消息。如果您处理该异常以降低调用链,那么调用代码将不知道它调用的代码已失败。