1

以下は、私が持っているセットアップの簡単な例です。私の問題は、例外が低レベルでスローされ、その後バブルアップすることです。しかし、より高いレベルのクラスは、より低いレベルのクラスの機能を使用するときにどんな恐怖が待ち受けているかを知りません。これにより、開発者は、恐ろしい「MyCustomException」の例外処理なしで Class3.DoWork3() を使用できるようになります。

私はこれにすべて間違って近づいていますか?同じ例外を複数回キャッチしてスローしたくありません (たとえば、Class2 でクリーンアップを行う必要はありません)。

public class Class1
{
    <exception cref="MyCustomException">description</exception>
    public void DoWork1()
    {
        throw new MyCustomException("I have failed you class1.");
    }
}

public class Class2
{
    public void DoWork2()
    {
        var classOne = new Class1();

        // Here I can see that DoWork1() will throw a 'MyCustomException'
        classOne.DoWork1();
    }
}

public class Class3
{
    public void DoWork3()
    {
        var classTwo = new Class2();

        // I can no longer see that Class2.DoWork2() will throw a 'MyCustomException'
        classTwo.DoWork2();
    }
}

コメントで発生したと思われる混乱を解消するために、現在検討している 2 つの解決策を示します。

  1. Class1 と同じ MyCustomException コメントで DoWork2 にタグを付けます。
  2. DoWork2 内で別の例外をスローし、この新しい例外でタグ付けします。このオプションは、より詳細なログ (たとえば、コードが実行パスのどこで失敗したか) を許可するため、最も堅牢に見えます。この方法は、単純化されたシナリオでは少しやり過ぎに思えます。そのため、(1) がこの問題に対する許容可能な解決策であるかどうか疑問に思っています。
4

2 に答える 2

1

.NET および Java での例外処理に関する主な制限の 1 つは、メソッドが予期する理由でメソッドからスローされる何らかのタイプの例外と、メソッドが予期する理由でスローされる同じタイプの例外をコードが区別できる標準化された手段がないことです。外部メソッドが予期しない理由で、ネストされたメソッドによってスローされます。メソッドの目的がユーザー提供のデリゲートを呼び出すことである場合、呼び出されたデリゲートによってスローされた例外と、それを呼び出すプロセスで発生した例外を確実に区別するために私が知っている唯一の方法は、メソッドに渡すことです。直接スローする例外に含めるか、ユーザー提供のコールバックの呼び出し中に発生するポリシー ラップ例外としてメソッドを持つ ID トークン。どちらの方法もそれほどエレガントではありません。

より深刻な問題が存在することを示すものから、操作が副作用なしで「完全に」失敗したことを示す例外を識別する標準化された方法がないため、コードが「深刻な」例外に依存して防止するべきではないことをお勧めします。 「伝染性の」データ破損。代わりに、例外によってオブジェクトが破損した状態のままになる可能性がある場合はいつでも、オブジェクトを明示的に無効にする必要があります、破損したデータがそこから読み取られて他の場所にコピーされるのを防ぎます (おそらく、唯一の正常なコピーであったものを上書きする可能性があります)。破損したオブジェクトが不要で、スタックの巻き戻しによってオブジェクトが無効化される状況では、問題はありません。無効化されたオブジェクトがシステム操作に不可欠であることが判明した場合、プログラムを強制的にシャットダウンする必要があり、オブジェクトを無効化することで、「重大な」例外をスローするよりも確実にシャットダウンを行うことができます。

残念ながら、C# も VB.NET も、この方法でオブジェクトを保護するための優れたパターンを提供していません。VB.NET は C# よりもいくらか優れた例外処理機能を備えており、適切なパターン (finallyスローされた例外に基づいてブロック内でアクションを実行するが、例外をキャッチしない) は、厄介ではありますが、その言語で実装できます。C# では、ブロック内で発生した例外を見つける唯一の方法tryは、キャッチして再スローすることです。このアクションには副作用があります。

于 2013-10-01T15:14:40.783 に答える
0

The Trouble with Checked Exceptionsというタイトルの Anders Hejlsberg との優れたインタビューがあります。(Anders は、C# プログラミング言語を設計したチームを率いていました。)

例外集約トラップに陥っています。おそらく、「下位レベルのシステムによってスローされる可能性のある例外は何ですか?」と尋ねるべきではありません。多くの場合、答えは何百もの固有の例外を含むリストになります。

代わりに、「開発者に有益な情報を提供するにはどうすればよいか」を自問する必要があります。コードが明示的にスローしている例外、またはまれに、発生する可能性が非常に高く、呼び出し元が特に関心を持っている可能性のある関連する例外を文書化する必要があります。コードを呼び出す開発者は、それらのエラーを処理する必要性を判断できます。その情報をコードの呼び出し元に渡すか、単に何もしないでください。結局のところ、例外は例外的なものであり、特定のレベルでは、どのデータベース エラーがスローされたかは問題ではありません。対応する手順は同じです (たとえば、可能であれば環境を安定させ、エラー ログに書き込み、実行を終了します)。

于 2013-12-17T05:45:35.760 に答える