将以下代码作为示例:

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块后,无论finallytry之间发生什么情况,finally部分中的代码都可以运行。

因此,在上面的代码中,外部try/finally确保在遇到任何异常时恢复Screen.Cursor。同样,内部try/finally可确保Obj在其生存期内引发任何异常的情况下被销毁。

如果要处理异常,则需要一个独特的try/except块。但是,在大多数情况下,您不应尝试尝试处理异常,而不要尝试。只需让它传播到主应用程序异常处理程序,该处理程序将向用户显示一条消息。

如果您处理该异常以降低调用链,那么调用代码将不知道它调用的代码已失败。

07-28 03:28
查看更多