違いのtry/catch /スローとのtry/catch(e)の間/スロー電子
try { }
catch
{ throw; }
と
try { }
catch(Exception e)
{ throw e;}
の違いは何ですか?
いつどちらか一方を使用する必要がありますか?
違いのtry/catch /スローとのtry/catch(e)の間/スロー電子
try { }
catch
{ throw; }
と
try { }
catch(Exception e)
{ throw e;}
の違いは何ですか?
いつどちらか一方を使用する必要がありますか?
構造
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;
}
第一及び第二のtry-catchブロックがまったく同じことです、彼らは単に現在の例外を再スローし、その例外は、その「ソース」とスタックトレースを維持します。
3番目のtry-catchブロックが異なります。例外がスローされると、ソースとスタックトレースが変更され、try-catchブロックを含むメソッドの行throw e
からこのメソッドから例外がスローされたように見えます。
どちらを使用しますか?それは本当にそれぞれの場合に依存します。
.Save()
メソッドを持つPerson
クラスを持ち、それをデータベースに保持するとします。アプリケーションが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メソッドに戻る情報が含まれます(問題を解決するのに十分かもしれませんが)。必要に応じて元の例外にアクセスできます。
あなたが選ぶべきInvalidPersonExceptionを期待している場合は、例外を期待しあり、最終的な発言として、あなたは本当に、すなわち、一般Exception
その1つの特定の例外をキャッチし、そしてべきではありません。
try { ... }
catch (InvalidPersonException e) { ... }
は、 へ try { ... }
catch (Exception e) { ... }
幸運!
最初のスタックトレースは、2番目のスタックトレースをリセットしている間は保持します。つまり、2番目の方法を使用した場合、例外のスタックトレースは常にこのメソッドから開始され、元の例外トレースを失うことになります。これは、例外ログの読者が例外の元の原因。
第二のアプローチでは、スタックトレースに追加情報を追加したいときに便利かもしれないが、それはこのように使用されます。
try
{
// do something
}
catch (Exception ex)
{
throw new Exception("Additional information...", ex);
}
の違いを議論するブログpostがあります。
あなたが(たとえばログイン)を再スローする前に例外を除いて何かをしたい場合は、
try { }
catch(Exception e)
{ throw }
を使用する必要があります。孤独なスローはスタックトレースを保持します。
と私はここで "スロー"を "スロー"と置き換えた場合どうなりますか? – Karim
Darinが指摘するように、 "throw e"はスタックトレースをリセットします。 –
パラメータのないキャッチとcatch(Exception e)
の違いは、例外への参照が得られることです。フレームワークバージョン2では、管理されていない例外がマネージ例外にラップされるため、パラメータなしの例外はもはや何のためにも役に立ちません。
throw;
とthrow e;
の違いは、最初のものが例外の再利用に使用され、2番目のものが新しく作成された例外のスローに使用されることです。 2番目の例外を使用して例外を再発行すると、新しい例外のように扱われ、最初にスローされた場所のすべてのスタック情報が置き換えられます。
だから、質問の中のいずれかの選択肢を使用しないでください。パラメータのないキャッチは使用しないでください。例外を再現するには、throw;
を使用する必要があります。
また、ほとんどの場合、すべての例外に対して、より具体的な例外クラスを基底クラスより使用する必要があります。予期した例外を捕捉するだけです。
try {
...
} catch (IOException e) {
...
throw;
}
あなたはすべての情報preservereする例外を再スローするとき、あなたは内部例外として、元の例外を持つ新しい例外を作成する任意の情報を追加したい場合は :
try {
...
} catch (IOException e) {
...
throw new ApplicationException("Some informative error message", e);
}
まあ知っている素晴らしいものです! – Myles
だから、なぜ2番目の? 最初のものだけを使う方が良いですか? – Karim
特定のexceptinonsをチェックする必要があるときに便利です - OutOfRangeExceptionが気になる - またはメッセージなどを記録する必要があります。最初はtry {} catch(...){と同様のワイルドカード例外ハンドラであるようです} C++で。 –