以下面的代码为示例:
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处理程序会有所帮助,但这似乎是一种肮脏的方式-它基本上忽略了Final块,更不用说从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
块。但是,在大多数情况下,您应该not尝试处理异常。只需让它传播到主应用程序异常处理程序,该处理程序将向用户显示一条消息。
如果您处理该异常以降低调用链,那么调用代码将不知道它调用的代码已失败。
您的原始代码并没有您想像的那么糟糕(但是很糟糕):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;
将被执行,无论您何时Obj.Free
将
// do something
会发生什么。即使发生异常(在try
之后),也会执行finally
块将!这就是try..finally
构造的重点!但是您也想还原光标。最好的方法是使用两个try..finally
构造:procedure TForm1.Button1Click(Sender: TObject);
var
Obj: TSomeObject;
begin
Screen.Cursor := crHourGlass;
try
Obj := TSomeObject.Create;
try
// do something
finally
Obj.Free;
end;
finally
Screen.Cursor := crDefault;
end;
end;
try finally
块来保护光标更改。为了避免编写这些代码,我使用如下代码: