26 delphi try-finally try-except
以下代码作为示例:
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仍然会被卡在一个小时玻璃中,因为代码在进入这些行之前已经被破坏了?
现在除非我误会,否则应该有一个异常声明来处理任何错误的发生,例如:
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块和之后以及在Exception块中两次使用相同的代码.
基本上我有时会有一些程序可能类似于我发布的第一个样本,如果我收到错误,光标会被卡在小时玻璃上.添加Exception处理程序会有所帮助,但它似乎是一种肮脏的方式 - 它基本上忽略了Finally块,更不用说从Finally到Exception部分的复制粘贴的丑陋代码.
如果这似乎是一个直截了当的问题/答案,我仍然非常学习德尔福.
如何正确编写代码来处理语句并正确释放对象和捕获错误等?
Dav*_*nan 34
你只需要两个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块.然而,在大多数情况下,你应该不尝试处理异常.只是让它传播到主应用程序异常处理程序,它将向用户显示一条消息.
如果你处理异常以降低调用链,那么调用代码将不知道它调用的代码是否失败.
And*_*and 17
您的原始代码没有您想象的那么糟糕:
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;
[但是,我也不介意
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更安全.
ain*_*ain 15
正如其他人所解释的那样,您需要使用try finally块保护光标更改.为了避免写这些,我使用这样的代码:
unit autoCursor;
interface
uses Controls;
type
  ICursor = interface(IInterface)
  ['{F5B4EB9C-6B74-42A3-B3DC-5068CCCBDA7A}']
  end;
function __SetCursor(const aCursor: TCursor): ICursor;
implementation
uses Forms;
type
  TAutoCursor = class(TInterfacedObject, ICursor)
  private
    FCursor: TCursor;
  public
    constructor Create(const aCursor: TCursor);
    destructor Destroy; override;
  end;
{ TAutoCursor }
constructor TAutoCursor.Create(const aCursor: TCursor);
begin
  inherited Create;
  FCursor := Screen.Cursor;
  Screen.Cursor := aCursor;
end;
destructor TAutoCursor.Destroy;
begin
  Screen.Cursor := FCursor;
  inherited;
end;
function __SetCursor(const aCursor: TCursor): ICursor;
begin
  Result := TAutoCursor.Create(aCursor);
end;
end.
现在你就像使用它一样
uses
   autoCursor;
procedure TForm1.Button1Click(Sender: TObject);
var
  Obj: TSomeObject;
begin
  __SetCursor(crHourGlass);
  Obj:= TSomeObject.Create;
  try
    // do something
  finally
    Obj.Free;
  end;
end;
和Delphi的引用计数接口机制负责恢复游标.
我认为最“正确”的版本是这样的:
procedure TForm1.Button1Click(Sender: TObject);
var
  Obj: TSomeObject;
begin
  Obj := NIL;
  Screen.Cursor := crHourGlass;
  try
    Obj := TSomeObject.Create;
    // do something
  finally
    Screen.Cursor := crDefault;
    Obj.Free;
  end;
end;
| 归档时间: | 
 | 
| 查看次数: | 52872 次 | 
| 最近记录: |