これは 「throw」と「throwex」の間に違いはありますか へのフォローアップの質問です。
スタックトレースをリセットせずに新しいエラー処理メソッドを抽出する方法はありますか?
[編集]「内部メソッド」とEarwickerが提供する別の 回答 の両方を試し、どちらがうまくいくかを確認します答えをマークする方が良いです。
あなたがそれを意味するかどうかはわかりませんが、あなたの他の質問での私の提案はこれに対処することでした。
例外が処理されたかどうかに関係なく、ハンドラーがブール値を返す場合は、catch句でこれを使用できます。
catch (Exception ex) {
if (!HandleException(ex)) {
throw;
}
}
はい;それがInnerExceptionプロパティの目的です。
catch(Exception ex)
{
throw new YourExceptionClass("message", ex);
}
これにより、独自のロジックを追加してから、独自の例外クラスをスローできます。 YourExceptionClassインスタンスのStackTraceはこのコードブロック内にありますが、InnerExceptionは、以前に発生したStackTraceでキャッチした例外になります。
.NET Framework 4.5では、この正確なシナリオをサポートする ExceptionDispatchInfo があります。これにより、含まれているスタックトレースを上書きすることなく、完全な例外をキャプチャして別の場所から再スローできます。
コメントでのリクエストによるコードサンプル
using System.Runtime.ExceptionServices;
class Test
{
private ExceptionDispatchInfo _exInfo;
public void DeleteNoThrow(string path)
{
try { File.Delete(path); }
catch(IOException ex)
{
// Capture exception (including stack trace) for later rethrow.
_exInfo = ExceptionDispatchInfo.Capture(ex);
}
}
public Exception GetFailure()
{
// You can access the captured exception without rethrowing.
return _exInfo != null ? _exInfo.SourceException : null;
}
public void ThrowIfFailed()
{
// This will rethrow the exception including the stack trace of the
// original DeleteNoThrow call.
_exInfo.Throw();
// Contrast with 'throw GetFailure()' which rethrows the exception but
// overwrites the stack trace to the current caller of ThrowIfFailed.
}
}
元のスタックトレースを使用して新しい例外を作成する必要はありません。そのスタックトレースは新しい例外を作成しなかったので、これは誤解を招く恐れがあります。
ただし、元の例外を「InnerException」として新しい例外に含めることができます。それはあなたが探していることをしますか?
より慎重にフィルタリングしたい例外をキャッチしているので、考えを変えて、それらを処理しないことを決定して、それらを再スローすることができますか?
これに本当に注意したいのなら、それは本当に良い考えではありません。そもそも例外をキャッチしない方がいいです。その理由は、特定のtry/catch
ハンドラーが、予期しない例外に対してネストされたfinally
ブロックを実行する決定を下すべきではないためです。たとえば、NullReferenceException
がある場合、別のそのような例外がスローされる可能性があるため、コードの実行を継続することはおそらく非常に悪い考えです。また、finally
ブロックは、他のコードと同様に単なるコードです。例外が初めてキャッチされるとすぐに、try/catch
の下のスタック上のfinally
ブロックが実行され、それまでに手遅れになります。別の例外が生成される可能性があります。これは、元の例外が失われること。
これは、(C#では)キャッチしたいすべての例外タイプに対して個別のcatch
ハンドラーを注意深く書き出す必要があることを意味します。また、例外タイプでのみフィルタリングできることも意味します。これは、従うのが非常に難しいアドバイスである場合があります。
他の方法で例外をフィルタリングすることは可能ですが、C#ではそうではありません。ただし、VB.NETで可能であり、BCL自体がVB.NETで少量のコードを記述してこれを利用しているため、より便利な方法で例外をフィルタリングできます。