48

C# Exception Handling Practices に関する他のいくつかの質問を読みましたが、探しているものを尋ねるものはないようです。

特定のクラスまたはクラスのセットに対して独自のカスタム例外を実装する場合。これらのクラスに関連するすべてのエラーは、内部例外を使用して例外にカプセル化する必要がありますか?

ソースから例外をすぐに認識できるように、すべての例外をキャッチする方がよいと考えていました。私はまだ元の例外を内部例外として渡しています。一方、例外を再スローするのは冗長だと思っていました。

例外:

class FooException : Exception
{
    //...
}

オプション 1: Foo はすべての例外をカプセル化します:

class Foo
{
    DoSomething(int param)
    {
        try 
        {
             if (/*Something Bad*/)
             {  
                 //violates business logic etc... 
                 throw new FooException("Reason...");
             }
             //... 
             //something that might throw an exception
        }
        catch (FooException ex)
        {
             throw;
        }
        catch (Exception ex)
        {
             throw new FooException("Inner Exception", ex);
        }
    }
}

オプション 2: Foo は特定の FooExceptions をスローしますが、他の例外を通過させます。

class Foo
{
    DoSomething(int param)
    {
        if  (/*Something Bad*/)
        {
             //violates business logic etc... 
             throw new FooException("Reason...");
        }
        //... 
        //something that might throw an exception and not caught
    }
}
4

8 に答える 8

55

FooExceptionライブラリに関する私の経験に基づいて、いくつかの理由から、(予想できる) すべてを でラップする必要があります。

  1. 人々はそれがあなたのクラス、または少なくともそれらの使用法に由来することを知っています。彼らが見れば、彼らはFileNotFoundExceptionそれを探しているかもしれません。あなたは彼らがそれを絞り込むのを手伝っています。(スタック トレースがこの目的を果たしていることがわかったので、この点は無視してかまいません。)

  2. より多くのコンテキストを提供できます。独自の例外で FNF をラップすると、「この目的のためにこのファイルをロードしようとしましたが、見つかりませんでした。これは、考えられる正しい解決策を示唆しています。

  3. ライブラリはクリーンアップを正しく処理できます。例外のバブルを放置すると、ユーザーにクリーンアップを強いることになります。あなたがしていたことを正しくカプセル化した場合、彼らは状況を処理する方法を知りません!

など、予想できる例外のみをラップすることを忘れないでくださいFileNotFoundExceptionラップして最高のものを期待しないでください。

于 2011-01-21T16:36:41.023 に答える
19

このMSDN-best-practises をご覧ください。

throwキャッチされた例外を再スローする場合は、代わりに使用することを検討してくださいthrow ex。この方法では、元のスタック トレース (行番号など) が保持されるためです。

于 2011-01-21T16:37:00.623 に答える
6

カスタム例外を作成するときは、常にいくつかのプロパティを追加します。1 つはユーザー名または ID です。ユーザーに表示されるテキストを運ぶために DisplayMessage プロパティを追加します。次に、Message プロパティを使用して、ログに記録される技術的な詳細を伝えます。

ストアド プロシージャの名前と渡されたパラメーターの値をキャプチャできるレベルで、データ アクセス レイヤーのすべてのエラーをキャッチします。またはインライン SQL。おそらくデータベース名または部分的な接続文字列です(資格情報はありません)。これらは、Message または独自の新しいカスタム DatabaseInfo プロパティに入れることができます。

Web ページについては、同じカスタム例外を使用します。Message プロパティにフォーム情報を入力します。ユーザーが Web ページのすべてのデータ入力コントロールに入力した内容、編集中のアイテムの ID (顧客、製品、従業員など)、およびユーザーのアクションです。例外が発生したときに取っていました。

したがって、あなたの質問によると、私の戦略は次のとおりです。例外について何かできる場合にのみキャッチします。多くの場合、私にできることは詳細をログに記録することだけです。そのため、これらの詳細が利用可能な時点でのみキャッチし、再スローして、例外が UI までバブルアップするようにします。そして、カスタム例外に元の例外を保持します。

于 2011-01-21T16:44:25.513 に答える
3

カスタム例外の目的は、詳細なコンテキスト情報をスタックトレースに提供して、デバッグを支援することです。オプション 1 の方が優れています。これがないと、例外がスタックの「下位」で発生した場合に、その「発生元」を取得できないためです。

于 2011-01-21T16:34:07.597 に答える
1

例外をキャッチするときにコードが知っておくべき最も重要なことは、残念ながら Exception オブジェクトから完全に欠落していますが、「あるべき」ものに対するシステムの状態です (おそらく、何か問題があったために例外がスローされたのでしょう)。LoadDocument メソッドでエラーが発生した場合、ドキュメントが正常に読み込まれなかったと考えられますが、少なくとも 2 つのシステム状態が考えられます。

  1. システムの状態は、ロードが試行されなかったかのようになる場合があります。この場合、ロードされたドキュメントなしで続行できるのであれば、アプリケーションが続行することは完全に適切です。
  2. システム状態が十分に破損している可能性があるため、保存できるものを「リカバリ」ファイルに保存し (ユーザーの正常なファイルを破損している可能性のあるデータで置き換えることは避けてください)、シャットダウンすることをお勧めします。

明らかに、これらの両極端の間には、他の可能な状態がしばしば存在します。状態 #1 が存在することを明示的に示すカスタム例外を作成するように努めることをお勧めします。また、予見可能であるが避けられない状況が原因である可能性がある場合は、おそらく #2 の例外を作成することをお勧めします。発生して状態 #1 になる例外は、状態 #1 を示す例外オブジェクトにラップする必要があります。システムの状態が損なわれる可能性があるような方法で例外が発生する可能性がある場合は、例外を #2 としてラップするか、パーコレートできるようにする必要があります。

于 2011-03-22T18:21:01.907 に答える
1

オプション 1:throw new FooException("Reason...");try / catch ブロックの外側にあるため、キャッチされません

  1. 処理したい例外のみをキャッチする必要があります。
  2. 例外に追加のデータを追加しない場合はthrow;、スタックを強制終了しないので使用してください。オプション 2 では、catch 内で何らかの処理を行いthrow;、元のスタックで元の例外を再スローするように呼び出すだけです。
于 2011-01-21T16:34:29.380 に答える
1

Visual Studio で 'Exception' のコード スニペットを実行すると、優れた例外記述のテンプレートが得られます。

于 2011-01-21T16:34:16.560 に答える
0

オプション 2 が最適です。ベストプラクティスは、例外で何かをする予定がある場合にのみ例外をキャッチすることだと思います。

この場合、オプション 1 は、独自の例外で例外をラップしているだけです。それは価値を追加せず、クラスのユーザーは ArgumentException をキャッチするだけではなくなります。たとえば、FooException をキャッチして内部例外を解析する必要もあります。内部例外が例外でない場合は、再スローする必要がある有用な何かを行うことができます。

于 2011-01-21T16:35:25.313 に答える