2010-12-08 24 views
3

doA()がdoB()を呼び出してdoC()を呼び出すことがわかっているC#プログラムで、doA()、doB()、およびdoC()の3つの関数があるとします。C#での例外伝播

doC()はデータベースとやりとりする必要があるため、ユーザーの注意を引く必要がある解決できない例外が生成される可能性があることがわかりました。現時点では、doC()でtry/catchブローでエラーをスローするコードがあり、別のtry/catchでdoB()でdoC()が呼び出され、同様にdoA()でdoB try/catchブロック内の()を使用します。これにより私はスローを使うことができます。例外をユーザーに表示するために何かを合理的に行うことができるdoA()まで例外をキックする。

これは少し残酷に思えます。 doB()またはdoC()の例外を処理する予定がないので、try/catchブロックを取り除くことができるのであれば、私は疑問に思います。

最後にブロックが含まれていないと仮定すると、このような状況を処理するためのベストプラクティスは何ですか?

答えて

10

あなたのcatchブロックは、ちょうどこのようにしている場合:

catch (Exception) 
{ 
    throw; 
} 

その後、彼らは本当に無意味です。例外を実際に処理しているわけではありません。try/catchを気にしないでください。

個人的に私は私のコードでは非常に少数のtry/catchブロックを持っている - と暗黙ののtry/finallyブロックがたくさんありますが、ほとんどはusing文によるものです。

5

はい私はtry/catchブロックを取り除くでしょう - 例外をトップレベルまで伝播させてそこにキャッチするようにしてください。それはスタックトレース情報を破壊するとして、次の変化が実際に有害であるが、ちょうどthrow;で再スローする例外をキャッチすることは、単に便利ではありません:あなたが何かをしようとする(あるいはしようとしている場合

catch (Exception exception) 
{ 
    throw exception; 
} 
5

あなただけキャッチする必要があります伝播を止める)。あなたがキャッチしないと、それは呼び出し元のキャッチに移動します。あなたのケースでは、doA()(またはそれを扱うことができる場所によっては呼び出し元)がtry/catchを必要とする唯一の関数だと思われます。

2

例外がコールスタックをバブルアップします。

例外が発生したメソッドがそれを処理しない場合、メソッドの呼び出し元はそれを取得します。呼び出し元がそれを処理しない場合は、フレームワークがそれを処理してアプリケーションをクラッシュするまで、コールスタックをさらに上に移動します。

あなたの質問に答えるには、あなたのケースで例外を再現する必要はありません。

0

IMHOでは、可能な限り少数の例外をキャッチする必要がありますが、実際には例外をキャッチするのはかなり高価な操作です。

アプリケーションレイヤーを越えている場所で、1つのレイヤーにログオン/再スローしたい場合があります。また、次のレイヤーもまたキャッチする必要があります。しかし、あなたのケースでは、それは単なるレイヤーなので、コールスタックの最も高い場所で、例外を使って何かできること、ログに記録してビジネスロジックを行うことができます。

+1

あなたの声明の真実性/偽りにはまっていません。「実際に例外をキャッチするにはかなり高価です」ということは、実際に重要であると私に確信させることです。 – jason

+0

あなたのアプリケーションのパフォーマンスが重要であると私には言いません。 – MStodd

+0

あなたは完全にその点を見逃しているか、それともコミュニケーションの効果的な仕事をしていませんでした。後者はそういう意味で私の謝罪を受け入れてください。私は精緻化します。私は真剣に例外をキャッチするパフォーマンス特性が重要であることを真剣に疑っています。ほとんどの場合、現実的なアプリケーションではボトルネックになることはまずありません。覚えておいてください。例外は例外的な状況です。さらに、例外は通常、システムの状態が悪いことを示し、その時点でパフォーマンスはほとんど問題ではありません。 – jason

0

要するにあなたの質問に対する答えははいです。例外をキャッチする唯一の理由は、それを使って何かをすることだけです。 DoC()で便利なことができない場合は、それをバブルアップしてください。

何かがキャッチされないように、(通常はwinフォームアプリケーションのイベントハンドラで)コードのエントリポイントでtryブロックを実行することは、常に良い習慣です。その時点で、それを使って何ができるかは、ユーザーに伝えます。

ただし、適切なアクションをとることができる場合は、適切な場合には、いくつかの下位レベルハンドラを配置することもできます。たとえば、doC()では、デッドロックに関連する例外をキャッチして再試行することができます。あるレベルでは、制約エラーを捕まえて、より意味のあるユーザー指定のエラーをその場で投げたい場合もあります。私にはblog post about that hereがあります。

0

あなたは3レベルで何をしているのかは分かりませんが、どのレベルでも違うことがありますが、スタックの一番上には1レベルの例外しかありませんさまざまなタイプの例外が存在する可能性があります。これは、広範な例外タイプを使用し、次に明確な情報を持たない特定の例外タイプを使用するように強制します。

したがって、投げる例外のタイプによって異なります。