9

次のルーチンがあるとします。

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;

exceptとをfinally転置することの意味は何ですか? 両方の方法で多くの投稿を見てきましたが、どの場合にどちらが適切であるかについての明確な説明を見たことがありません (上記の構成で、ブロックがブロックのfinally実行されることはまだ興味深いと思います!)。except

try..except混合とtry..finallyブロックは良い考えではないことを示唆する投稿も見ました。一部の Indy ルーチンなど、ルーチンが通常の操作の一部として例外をスローする状況で、どのように回避できますか?

4

1 に答える 1

12

これを書く唯一の正しい方法はありません。2 つの変種は異なることを行います。あるシナリオでは 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 ブロックとブロックがどのように動作するかをまだ完全には理解していません。

よく見られるよくある間違いは、できるだけ早く例外をキャッチして処理したいという欲求です。それは間違った戦略です。例外についての重要な点は、例外が発生することを意図しておらず、通常、例外が発生したときに何をすべきかわからないということです。あなたの目標は、例外をできるだけ遅く処理することです。大部分のコードでは、例外を処理するべきではありません。エラーを処理できるコード内のポイントまで、それらを上向きに浮かせます。

于 2015-03-04T21:54:38.470 に答える