時々、私は魔女のタイプの例外を投げるべきかわからない。したがって、私は通常Exception()をスローします。これについての良い記事はありますか?
6 に答える
Cwalina と Abrahms による「Framework Design Guidelines」は、このトピックを非常によくカバーしています (IMHO)。
こちらからオンラインで無料で入手できます。または、本 (無料ではありません)はこちら (英国)またはこちら (米国) から入手できます。例外の設計ガイドラインというタイトルのセクションを参照してください。
一般的な例外をスローすることの問題は、スタックのさらに上位のコードが適切に処理する能力を制限することです (つまり、ベスト プラクティスは、フォールバックする前に可能な限り具体的な例外をトラップし、処理できるものだけをキャプチャすることです)。
Jeffrey Richter には、 C# による CLRでの例外処理 (System.Exception 名前空間に関する情報を含む) に関する優れたセクションがあります。
システムの状態に基づいて、例外をいくつかのカテゴリに分割することをお勧めします。
- この方法は失敗したため、何もしませんでした。基になるデータの状態は乱されておらず、おそらく有効です。典型的なシナリオ:コレクションから存在しないオブジェクトを取得しようとするか、すでに存在するオブジェクトを追加しようとします。別の考えられるシナリオ:データ損失を引き起こしてはならない場合の通信タイムアウト(そして、問題が単に相手側が遅すぎるというだけの場合、操作を再試行していた場合は成功する可能性があります)。
- メソッドが失敗したため、基になるデータ構造が乱れたか、基になるデータ構造が以前に破損している可能性があります。このデータ構造を検証するための手順が実行されない限り、このデータ構造を使用してそれ以上の操作を試行しないでください。別の考えられるシナリオ:レコードが部分的に取得されたときに通信タイムアウトが発生し、部分的に取得されたデータが失われるようになりました。プロトコルによっては、接続に対して何らかの回復アクションを実行するか、接続を閉じて新しい接続を開始する必要がある場合があります。
- システムの状態に重大な問題があり、回復できない可能性があります。
残念ながら、既存の.net例外はそのパターンのようなものには適合しません。ThreadAbortException、CpuHasCaughtFireException、'normal' Exceptionなどが派生したタイプExceptionBaseがあり、すべての'normal'例外がExceptionから派生していれば良かったでしょう。.net 4.0はそのような設計に多少の不満があることは理解していますが、正確な仕組みはわかりません。いずれにせよ、ユーザー定義の例外は上記のようにグループに分割し、各グループのすべての例外は他のグループとは異なる共通の祖先を共有することをお勧めします。
エラーからの回復を試みていない場合はException
、文字列を含む をスローして、何が問題だったかを伝えることができます。(または、発生したエラーに関係なく同じアクションを実行する場合)。
メッセージに例外名を入れるのではなく、新しい例外名を使用することで、何が問題なのかをプログラマーに明らかにする以外に、例外には、特定の例外から回復するのに役立つデータを含めることができます。
たとえば、 anArgumentNullException
にはプロパティParamName
があり、例外をスローするときに設定する必要があります。呼び出し元がそれをキャッチすると、このプロパティを調べて、エラーの原因となった引数に新しい値を渡すか、関連するエラーを出力して何が問題なのかをプログラマーに知らせることができます。
残念なことに、(多くのオープンソース API などで) 例外が最大限に活用されることはめったになく、何が問題なのかをプログラマーに知らせるために単純に挿入されることがよくあります。ParamName
プロパティをキャッチしたときにプロパティを読み取る予定がない場合、これら 2 つの間に大きな違いはありません。(多くの人は気にせず、Exception
とにかく捕まえるだけです)。
throw new ArgumentNullException("arg1");
throw new Exception("arg1 is null");
エラーから完全に回復するのは難しい場合がありますが、一部のアプリケーションでは、必要なすべての詳細を提供できるカスタム例外を作成することが望ましい場合があります。
今のところ、Exception
VS でオブジェクト ブラウザー検索を実行し、既に何があるかを確認します。それらの名前は一目瞭然なので、適切なものを選択できるはずです.
まあ、やってはいけないことは、自分自身を投げるException
ことです。
常に適切なサブクラスを探してください。
どの例外をいつスローするかを詳しく説明している出版物は知りませんが、ほとんどのケースを処理する必要がありますArgumentException
。InvalidOperationException
個別のケースが発生した場合は、個別の質問をしてください。
Krzysztof Cwalina (「Microsoft の .NET Framework チームのプリンシパル アーキテクト」) による記事「Choosing the Right Type of Exception to Throw 」(スローする適切な種類の例外の選択)が、この点に光を当てています。スローする適切な例外の選択と、カスタム例外の作成に関するガイダンスを扱います。