デルファイ7では、「試用…レイズを除く。 end; `意味がありますか?

StackOverflow https://stackoverflow.com/questions/805109

質問

メンテナンスしているDelphi 7コードの中には、次のようなインスタンスがたくさんあることに気付きました。

with ADOQuery1 do begin
  // .. fill out sql.text, etc
  try
    execSQL;
  except
    raise;
  end;
end;

これらのtryブロックは何もしないので削除できるように思えます。ただし、微妙な副作用の可能性には警戒しています。

これらのブロックがなければ、これらのブロックが実際に実行できるインスタンスを考えることができますか?

役に立ちましたか?

解決

このコンテキストでは、例外ブロックがキャッチした例外を単に再発生させるため、raise操作は効果がなく、削除する必要があります。通常、raiseは、適切なエラー処理が利用できない場合にブロックの終わりに制御を移すために使用されます。以下では、カスタム例外を処理しますが、他の例外は他の場所で処理する必要があります。

try
  someOperation;
except
  on e: ECustomException do
    SomeCustomHandelr;
  else
     begin
       // the raise is only useful to rethrow the exception to an encompasing 
       // handler.  In this case after I have called my logger code. as Rob
       // mentioned this can be omitted if you arent handling anything because
       // the compiler will simply jump you to the next block if there is no
       // else.
       LogUnexpectedException('some operation failed',e);
       raise;
     end;
end;

「レイズ」なしの似たようなフォームがあることに注意してください。例外を食べる/隠すという副作用があります。うまくいけば、競争でのポジションに移動した非常に不cru慎な開発者による練習。

with ADOQuery1 do begin  
  // .. fill out sql.text, etc  
  try    
    execSQL; 
  except
    // no handler so this just eats any "errors"    
  end;

他のヒント

上記のコードスニペットの例外コードを削除しても違いはありません。削除できます(読みやすさが低下しているため、すべき)。

さて、ここに2つの質問があります。

まず、それは 意味があります:execSQLが例外をスローすると、tryブロックによってキャッチされ、exceptに転送されます。その後、レイズによって次の上位ブロックに転送されます。

次に、有用ですか?おそらくない。ほぼ確実に、次の3つのいずれかの結果です。

  1. 先のとがった髪の人は、「例外をスローできるすべての操作はtryブロック内になければならない」と述べたコーディング標準を書きました。
  2. 誰かが戻ってきて、 execSQL の文言によって作成された例外を、より意味のある他の例外に変えるつもりでした。
  3. 書いたものが子宮環境に例外を心配させるのと同型であることに気づかなかった新しい人がいるので、彼らはそれをする必要があると思った。

少し早く答えたかもしれません。最後をご覧ください...
そうであるように、アプリケーションには役に立たない
期間!

「なぜ」と言うと、側。レイズの前に挿入された/ある/他の場所にある/ある種のロギングコードがある場合、例外処理を標準化することもできます:

  try
    execSQL;
  except
    // Log Exception..
    on E: Exception do
    begin
      LogTrace(Format('%s: Exception Message[%s]',[methodname, E.Message]));
      raise;
    end;
  end;

またはクリーンアップコードの場合:

  try
    execSQL;
  except
    //some FreeAndNil..
    raise;
  end;

更新:いくつかの使用例があります...
... raise 行にブレークポイントを配置して、そのコードブロックのコンテキストで何が起こっているかを確認できるようにします。

このコードは、元のプログラマーが 'Raise'にブレークポイントを配置し、ソース内で考えられる原因により近い例外を確認できるようにすること以外は何もしません。その意味では、完全に合理的なデバッグ手法です。

実際には、これをFranç oisの回答へのコメントとして投稿する必要がありますが、フォーマットされたコードをそこに挿入できるかどうかわかりません:(だから、これを回答として投稿しています。

2mghie:

  
    
      

2つ目は完全にユニディオマティックで、代わりに最終的に使用します。

    
  

いいえ、「最終的に」オブジェクトを常にクリーンアップします。 " Except" -例外のみ。オブジェクトを作成、入力、返す関数の場合を考えてみましょう:

function CreateObj: TSomeObj;
begin
  Result := TSomeObj.Create;
  try
    ... // do something with Result: load data, fill props, etc.
  except
    FreeAndNil(Result); // oops: bad things happened. Free object to avoid leak.
    raise;
  end;
end;

「最後に」を入れた場合there-関数は常にnilを返します。 &try; try"を省略した場合まったくブロック-" ..."で例外が発生した場合、リソースリークが発生します。

PSもちろん、「最終的に」を使用できます。 ExceptObjを確認しますが、... ...いではありませんか?

タイトルには非常に広範な質問が含まれていますが、その説明にはより具体的な例があります。そのため、例からどのように進行するかという質問に答えると、ここで既に述べたことに役立つものが疑いなく追加される可能性があります。

しかし、たぶん Blorgbeardは、レイズを除いて、 tryにとってまったく意味があるかどうかを知りたがっています。終了。 Delphi 7では、正しく思い出せば、 Exit try-finally ブロックの finally 部分をトリガーします(ある種のように)例外)。誰かがそのような振る舞いを自分のタスクに不適切であると考えるかもしれません。問題の構造を使用することはかなりの回避策です。

ここで単一の raise; を使用するのは依然として奇妙ですが、意味ではなく有用性について話すべきでした。チャーリーがきちんと観察したように。

このコードは、ブロックを除いてこの試行なしですでに発生する例外を再発生する以外は何もしません。安全に削除できます。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top