2

私の知る限り、try / catchを使用するのは、例外を実際に処理する場合のみであり、レポートしてログに記録してからアプリケーションをクラッシュさせるだけではありません。それ以外の場合は、意味のあるさまざまなシナリオをチェックするか(sth == nullの場合など)、または-目的が例外をログに記録してアプリケーションをクラッシュさせるだけの場合-AppDomain.UnhandledExceptionを使用することをお勧めします。しかし、これは常に当てはまり、その理由は何ですか?

次のメソッドを想定します。このメソッドは、配列を受け入れ、データベースおよびファイルシステムの操作を実行した後にMemoryStreamを返します。

MemoryStream Read (int[] IDs)
{
    try
    {
        using (SqlConnection connection = new SqlConnection(connection_string))
        {
            connection.Open();    

                        // a bunch of code executing SQL queries & constructing MemoryStream, which is returned at the end of the block
        }
    }
    catch (Exception e)
    {
        // report the exception to the user & log it
        throw; // pointles??                
    }
}

次のような、例外的/望ましくない動作と見なすことができる複数の状況があります。

  • 引数(IDs [])がnullであり、
  • SQL接続の確立に失敗しました。
  • 特定のSQLクエリの実行に失敗しました。

これらのケースはすべて例外と見なされますが、例外をログに記録したいだけの場合(その後クラッシュ)、すべてをtry / catch内に置くことは、おそらく悪い習慣ですが、なぜですか?上記の場合の最良の処理動作は何でしょうか?try / catchを完全に避け、ifステートメントを使用してnull参照をチェックし(このような場合はnullを返します)、AppDomain.UnhandledExceptionを使用して他のすべてをログに記録しますか?try / catchを使用しますが、ifステートメントを使用して内部のnull参照をチェックしますか(その場合はreturn)?他に何かありますか?

4

3 に答える 3

2

アプリをクラッシュさせるためだけにtry/catchステートメントを使用してコードをペッパーすることは、生産的ではありません。CLRはすでにそれを処理します。そして、原因を診断するための適切な情報を生成するためのAppDomain.UnhandledExceptionがあります。

何かをクリーンアップする必要がある非常に特殊なケース、たとえば、置き続けたくないファイルの場合にのみ、try/catchの作成を検討する必要があります。それ自体が非常に厳しい要件ですが、catchブロックが実行される保証はありません。StackOverflowExceptionやExecutionEngineExceptionのように例外が厄介な場合はそうではありません。または、プログラムが自分でクリーンアップしない、誰かが電源コードをつまずいたり、タスクマネージャーからプロセスを強制終了したりする一般的な理由。

于 2013-01-31T14:47:59.480 に答える
1

try / catchを使用するのは、例外を実際に処理する場合のみであり、レポートしてログに記録してからアプリケーションをクラッシュさせるだけではありません。

最初の部分に同意しますが、呼び出し側の層を制御できない場合は、層の境界にロギングを追加することが重要であると付け加えます。たとえば、デバッグ情報(スタックトレースなど)が常に通信レイヤーを適切に通過するとは限らないため、サーバーにログを記録するために、最上位のメソッドでWebサービスで発生するすべての例外をログに記録します。

あなたの特定の例では、他の例外を「自然に」発生させることができる「例外的な」条件をチェックします。あなたの特定の例のために:

  • 引数(IDs [])がnullであり、
  • SQL接続の確立に失敗しました。
  • 特定のSQLクエリの実行に失敗しました。

null最初の理由については、1つの理由で引数を確認します。Aは、例外の原因について、それが発生した場所NullReferenceException以外のコンテキストを提供しませnullの引数を追加できるので、チェックしてから新しい例外をスローする方がはるかに好きです。nullである理由を見つけるために、まだ掘り下げる必要があるかもしれませんが、デバッグにかかる​​時間を大幅に節約できます。nullArgumentNullException

SQL例外には、適切なエラー情報が含まれているため、通常は自然に発生する可能性があります(例"undeclared variable '@arg'") 。

于 2013-01-31T15:06:30.857 に答える
1

私は最近、このトピックについて自分で読み始めました。私の基本的な理解は次のとおりです。

  1. 例外を処理する予定がある場合にのみ、例外をキャッチします。
  2. try / catchを使いすぎると、例外を飲み込んだり、貴重なスタックトレース情報が失われたりする可能性があり、保守性の問題が発生する可能性があります(エラー/ログを標準化することにした場合はどうなりますか?)。代わりに、try / finalを使用するか、ブロックを使用してクリーンアップを実装してください。
  3. グローバル例外ハンドラを介して境界で例外をキャッチします。
  4. AppDomain.UnhandledExceptionを使用して、名前が示すとおり、未処理の例外をログに記録します。これらをログに記録しないと、ログビューアにCLRの「Windowsエラー報告」エントリと、実際には役に立たないいくつかのダンプファイルしか表示されません。AppDomain.UnhandledExceptionを利用することは常に良い考えです。そうすれば、アプリケーションがクラッシュした場合にその理由がわかります。

例外の「処理」は、必ずしもクリーンアップまたは遡及ロジックを意味するわけではないことに注意することが重要です。処理とは、エラーをよりユーザーフレンドリーなものにフォーマットしたり、誰にも見られたくない機密性の高いスタックトレースを非表示にしたりすることを意味します。私は定期的に詳細なエラーをログに記録し、フォーマットされたエラーを返します。

繰り返しますが、これは私が最初に集めたものです。以下はいくつかの情報源です:

経験則の優れた例外管理ルール

例外の理解と使用

于 2013-01-31T15:07:57.347 に答える