【问题标题】:Delphi - What is the "correct" order for except and finally blocks?Delphi - except 和 finally 块的“正确”顺序是什么?
【发布时间】:2015-05-05 22:44:51
【问题描述】:

假设我有以下例程:

function ReadFile(f : TFilename) : Boolean;
var
  fs : TFileStream;
begin
  Result := False;
  try
    fs := TFileStream.Create(f, ...);
    try
      // read file ...
      Result := True;
    finally
      FreeAndNil(fs);
    end;
  except
    // handle exceptions ...
  end;
end;

exceptfinally 转置有什么影响?我已经看到很多关于它们的帖子,但我还没有看到一个明确的解释,说明在哪种情况下哪个是合适的(我仍然认为在上面的构造中,finally 块执行 except 块之后!)。

我还看到一些帖子暗示混合使用 try..excepttry..finally 块不是一个好主意。在例程作为正常操作的一部分抛出异常的情况下(例如在某些 Indy 例程中),如何避免这种情况?

【问题讨论】:

  • “在上面的构造中,finally 块在 except 块之后执行” - 这是不正确的。

标签: delphi exception-handling try-except try-finally


【解决方案1】:

没有一种正确的写法。这两个变体做不同的事情。您可能在一种情况下更喜欢一个版本,在不同的情况下更喜欢另一个版本。

版本 1,最后是最内层

function ReadFile(f : TFilename) : Boolean;
var
  fs : TFileStream;
begin
  Result := False;
  try
    fs := TFileStream.Create(f, ...);
    try
      // read file ...
      Result := True;
    finally
      FreeAndNil(fs);
    end;
  except
    // handle exceptions ...
  end;
end;

第 2 版,最后是最外层

function ReadFile(f : TFilename) : Boolean;
var
  fs : TFileStream;
begin
  Result := False;
  fs := TFileStream.Create(f, ...);
  try
    try
      // read file ...
      Result := True;
    except
      // handle exceptions ...
    end;
  finally
    FreeAndNil(fs);
  end;
end;

最大的区别在于如果TFileStream.Create 引发异常,代码的行为方式远非难以置信的可能性。在版本 1 中,异常将在 ReadFile 内被捕获和处理。在版本 2 中,异常将从ReadFile 传递到异常处理程序链的上游。

旁白

你说:

我仍然觉得奇怪的是,在上面的构造中,finally 块在 except 块之后执行!

对于您问题中的代码(上述版本 1),情况并非如此。也许你还没有完全理解 finally 和 blocks 是如何运作的。

一个经常被观察到的常见错误是希望尽快捕获和处理异常。那是错误的策略。关于异常的全部意义在于它并不意味着发生,并且当它发生时您通常不知道该怎么做。您的目标是尽可能晚地处理异常。对于绝大多数代码,您根本不应该处理异常。让它们向上浮动到代码中能够处理错误的点。

【讨论】:

  • 好的,我想我在执行顺序上错了。我确信我已经通过一个例程来测试它,因为它处理了一个被捕获的异常,但我猜不是。感谢您的回答。很好,很彻底。
猜你喜欢
  • 2022-01-04
  • 2013-07-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-17
  • 2013-12-30
  • 2014-05-04
  • 2017-09-20
相关资源
最近更新 更多