德尔福 - 什么是"正确"订购除了和最后块?

时间:2015-03-04 19:21:26

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

假设我有以下例程:

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例程中),如何避免它?

1 个答案:

答案 0 :(得分:12)

没有一种正确的方法来写这个。这两种变体做了不同的事情。您可能更喜欢一个场景中的一个版本,另一个场景中的另一个版本。

版本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不是这样。也许你还没有完全理解最终和块如何运作。

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