.netで例外を処理する

私はここでいくつかの質問をし、例外処理についてのいくつかの記事を読んだが、あなたがいつすべきか、例外を処理してはならない時を本当に把握しているとは思わない。私が読んだ記事では、「あなたが回復できる例外を処理するだけです」ということは、それが意味することは何ですか?例外を処理できない場合、私は何をしますか?それはスタックの上に伝播させますか?私がそれを処理しない場合、どのように私はそれを記録し、ユーザーフレンドリーなエラーメッセージを表示することができます。ほとんどの人はWebアプリケーションやWebサービスで何をしていますか?

例として、私はSQLからデータを引き出す下層のデータ層を持っています

try{
  //do something with db
}catch(SqlException ex){
 //what should i do here
 //should i call code again to retry getting data from db
}catch(Exception ex){
 //should i even catch exception of type exception
}

下位層で例外を処理するにはどうすればよいですか?例外をバブルアップさせるべきでしょうか?もしそうなら、私はsqlexception型の例外をキャッチしたいと思うなら、ライブラリsqlexceptionへの参照が必要ですが、確かにデータアクセスとは関係のない層でそのライブラリを参照する必要はありません。

1
追加された 著者 Brian Dishaw,

3 答え

いくつかの簡単な基本ルール:

  • 例外を処理するには、例外の原因となったコードが開始される前の状態とプログラムの状態が正確に一致している必要があります。変数を元の状態に戻す多くのcatchとfinallyブロックが必要です。

  • プログラムをキャッチしても意味のある方法でプログラムを実行できる場合にのみ、例外を処理することを検討してください。例えば、データベースサーバがオフラインのときに便利なことはありません。プログラムを停止することもできます。

  • 人間が是正措置を取る必要がある場合(ほとんどの場合そうする)、問題を解決するのに十分な情報があることを確認してください。例外をUIレイヤーにバブルアップさせます。例外を解釈しないでください(たとえば、 "データベースを更新できませんでした")、正確な例外メッセージとスタックトレースを表示しないでください。

  • AppDomain.CurrentDomain.UnhandledExceptionのハンドラを実装し、e.ExceptionObjectの値を記録または表示します。未処理の例外を診断するのに役立ちます。どこにでもキャッチするのを避けるのに役立ちます。

2
追加された
あなたはスタックトレースを表示しないでください。そのセキュリティ上のリスクはない!!!!
追加された 著者 Richard Banks,
もちろん、あなたはどういうことを言っていますか?
追加された 著者 Hans Passant,

これはまだ早朝ですので、これはあまりにも簡単すぎますが、私はこの同じ質問に苦労していますので、ここで理解しています。

"回復できる例外のみを処理します"

私のここでの理解は、あなたがコードで何かを行うことができるレベルの例外を取得するということです。あなたの低レベルのコードの場合、あなたは例外を処理し、おそらくプロセスを再試行するためにあなたの 'プロセス'を変更することができる層に例外バブルをバックアップさせます。 (私は通常、スローされた場所でエラーを記録します。)

1
追加された
@DylanSmithは実際には良い点です。私は私のコードのさまざまな領域のために定義された異なるトレースを持っているので、私はちょうどこのメソッドを使用してコードを書いています。この方法で、ログは適切なトレースに書き込まれます...
追加された 著者 Nitax,
その最後のビットを除いて、一般的には良いアドバイス。ログに記録する場合は、可能な限り最高レベル(UIなど)で実行する必要があります。そうしないと、コード全体にエラーログが記録されます。それらをすべてバブルアップさせるだけなら、未処理の例外を記録するトップレベルの一般的なエラーハンドラを持つことができます。
追加された 著者 Dylan Smith,
Nitaxの答えを拡張するには、たとえば、システムのメモリ不足時にスローされるOutOfMemoryExceptionを処理しないでください。クラッシュする代わりに、ユーザーの作業を保存してアプリケーションを正常に終了します。
追加された 著者 Security Hound,

例外管理は大きなテーマですので、ここでは表面に触れるだけです。

    

記事のiveから、「あなたが回復できる例外を処理するだけです」と書かれています。

  

特定の例外から回復する方法がわからない場合は、通常はそれをキャッチすることはありません。それがWebアプリケーションまたはサービスの場合、Webサーバー自体がログと回復を処理します。

場合によっては、トランザクションを取り消したり取り消したりするなど、一般的なリカバリができるように例外をキャッチする必要があります。その場合、許容可能なアプローチは、  例外をキャッチし、汎用リカバリを行い、再度例外をスローします。

    

もし私が何をすれば例外を処理できないのですか?それはスタックをバックアップpropateさせますか?

  

はい。

    

もし私がそれを処理しないと、私はそれを記録し、ユーザーフレンドリーなエラーメッセージを表示することができます。ほとんどの人はウェブアプリケーションやウェブサービスで何をしますか?

  

Webサーバーは例外を記録します。 Webアプリケーションにユーザーフレンドリーなエラーメッセージを表示したい場合は、スタックの最上位レベルをキャッチ/ログして、エラーメッセージにリダイレクトすることができます。もう一度、私はSystem.Exceptionをキャッチしないでください - あなたのアプリがスローする例外のリストを作成し、各タイプに合わせたメッセージを表示する前にこれらの型だけをキャッチします。例外タイプのリストが増加するにつれて、コードを変更して新しい例外タイプをそれぞれ禁止するか、その例外タイプに新しいキャッチを追加します。

Webサービスでは、カスタム例外を作成して、それをWebサービスが提供する汎用例外へのノードとして追加できます。

あなたのコード例では、例外を予期していない限り、try ... catchを使用しません。

    

下位層で例外を処理するにはどうすればよいですか。私は例外をバブルアップさせるべきですか?

  

はい。

1
追加された
それに感謝します。非常にストレートです。もし私がウェブアプリケーションの最高レベルでキャッチするならば。どんなタイプの例外が私を捕まえるでしょうか。どこでも読書の状態は例外型の例外をキャッチしません
追加された 著者 Richard Banks,
いいですね。私はsqlexceptionをキャッチしたいと思うし、UIでそれをキャッチしたい場合は、例外の型を含む名前空間への参照を追加する必要があります。それは正しいようですか
追加された 著者 Richard Banks,
@リチャード:私はあなたのコメントに答えるためにテキストを変更しました。
追加された 著者 RoadWarrior,
@リチャード:私はアセンブリの参照(名前空間にアクセスする)は大したことではないと思います。あなたのコードを膨らませません。私は例外管理と名前空間の参照を別のクラスに入れて、すべてを隠して、他のクラスをランダムな名前空間で汚染しないようにする傾向があります。
追加された 著者 RoadWarrior,