回答:
構造
try { ... }
catch () { ... } /* You can even omit the () here */
try { ... }
catch (Exception e) { ... }
両方がブロック内でスローされたすべての例外をキャッチするという点で似ていtry
ます(そして、単にこれを使用して例外をログに記録しているのでない限り、避けてください)。これらを見てください:
try { ... }
catch ()
{
/* ... */
throw;
}
try { ... }
catch (Exception e)
{
/* ... */
throw;
}
try { ... }
catch (Exception e)
{
/* ... */
throw e;
}
最初と2番目のtry-catchブロックはまったく同じもので、現在の例外を再スローするだけで、その例外は「ソース」とスタックトレースを保持します。
3番目のtry-catchブロックは異なります。例外をスローすると、ソースとスタックトレースが変更されるため、このメソッドから、throw e
そのtry-catchブロックを含むメソッドのその行から例外がスローされたように見えます。
あなたはどちらを使うべきですか?それは本当にそれぞれの場合に依存します。
それをデータベースに永続化Person
する.Save()
メソッドを持つクラスがあるとしましょう。アプリケーションがPerson.Save()
メソッドをどこかで実行するとします。DBがPersonの保存を拒否した場合.Save()
、例外がスローされます。throw
またはthrow e
この場合に使用する必要がありますか?まあ、それは異なります。
私が好んでいることは:
try {
/* ... */
person.Save();
}
catch(DBException e) {
throw new InvalidPersonException(
"The person has an invalid state and could not be saved!",
e);
}
これにより、DBExceptionが、スローされる新しい例外の「内部例外」として配置されます。したがって、このInvalidPersonExceptionを検査すると、スタックトレースにはSaveメソッドに戻る情報が含まれます(問題を解決するにはこれで十分かもしれません)が、必要な場合は元の例外にアクセスできます。
最後の注意として、例外が予想される場合は、一般的な例外ではなく、その特定の例外を1つキャッチする必要がありますException
。つまり、InvalidPersonExceptionが予想される場合は、次のようにします。
try { ... }
catch (InvalidPersonException e) { ... }
に
try { ... }
catch (Exception e) { ... }
幸運を!
1つ目はスタックトレースを保持し、2つ目はリセットします。つまり、2番目のアプローチを使用する場合、例外のスタックトレースは常にこのメソッドから始まり、元の例外トレースを失うことになります。これは、例外の元の原因を見つけることができないため、例外ログを読む人にとっては悲惨です。 。
2番目の方法は、スタックトレースに追加情報を追加する場合に便利ですが、次のように使用されます。
try
{
// do something
}
catch (Exception ex)
{
throw new Exception("Additional information...", ex);
}
違いについて議論しているブログ投稿があります。
throw
vs とは別のものthrow e
です。
パラメータなしのキャッチとaの違いはcatch(Exception e)
、例外への参照を取得することです。フレームワークバージョン2以降、アンマネージ例外はマネージ例外にラップされるため、パラメーターなしの例外は何の役にも立ちません。
違いthrow;
とは、throw e;
最初のものは、例外を再スローするために使用される2つ目は、新しく作成された例外をスローするために使用されていることです。2番目の例外を使用して例外を再スローすると、新しい例外のように扱われ、最初にスローされた場所からのすべてのスタック情報が置き換えられます。
したがって、あなたは質問のどちらの選択肢も使用しないことをお勧めします。パラメータなしのキャッチを使用throw;
しないでください。また、例外を再スローするために使用する必要があります。
また、ほとんどの場合、すべての例外について、基本クラスよりも具体的な例外クラスを使用する必要があります。予期した例外のみをキャッチする必要があります。
try {
...
} catch (IOException e) {
...
throw;
}
例外を再スローするときに情報を追加する場合は、元の例外を内部例外として新しい例外を作成し、すべての情報を保持します。
try {
...
} catch (IOException e) {
...
throw new ApplicationException("Some informative error message", e);
}