考え
C#/.NET で例外をスローする代わりに、コールバックを使用することを考えています。
長所と短所
利点は
- チェックされていない例外の制御フローのような隠し goto はありません
- 特に複数の例外が関係している場合は、よりクリーンなコード
- スローされた例外はメソッド シグネチャに記載されており、呼び出し元は例外の処理について考える必要がありますが、アプリケーション全体の例外ハンドラー、"UnhandledExceptionHandler"、または null を簡単に渡すことができます。したがって、それらは「ソフト」チェック例外のようなものですが、メソッドをオーバーロードすることで後で例外をスローしたり、例外ハンドラーで「ハンドル」を呼び出さないようにすることで例外を削除したりできるため、より保守しやすくなっています)。
- 非同期呼び出しにも適しています
- 例外ハンドラーは、さまざまな場所でスローされるいくつかの例外を処理できます
- どの例外を処理する必要があるかを明示します。「NotImplementedException」のように処理したくない例外に対しては、通常の方法で例外をスローすることもできます。
デメリットは
- C# および .NET にとって慣用的ではない
- throwing メソッドは、すぐに戻り値を返すことによって制御フローを中断する必要があります。戻り値の型が値型の場合、これは困難です。
- ? (下記の質問を参照)
質問
なぜこれが使用されないのか疑問に思っているので、おそらくいくつかの重大な欠点を見逃しています。私が見逃した欠点は何ですか?
例:
それ以外の
void ThrowingMethod() {
throw new Exception();
}
と
void CatchingMethod() {
try {
ThrowingMethod();
} catch(Exception e) {
//handle exception
}
}
私はするだろう
void ThrowingMethod(ExceptionHandler exceptionHandler) {
exceptionHandler.handle(new Exception());
}
void CatchingMethod() {
ThrowingMethod(exception => */ handle exception */ );
}
と
delegate void ExceptionHandler(Exception exception);
どこかで定義され、「handle(...)」は null をチェックする拡張メソッドであり、スタック トレースを取得し、例外がスローされたときに例外ハンドラーがまったくない場合は「UnhandledException」をスローする可能性があります。
以前に例外をスローしなかったメソッドで例外をスローする例
void UsedToNotThrowButNowThrowing() {
UsedToNotThrowButNowThrowing(null);
}
//overloads existing method that did not throw to now throw
void UsedToNotThrowButNowThrowing(ExceptionHandler exceptionHandler) {
//extension method "handle" throws an UnhandledException if the handler is null
exceptionHandler.handle(exceptionHandler);
}
値を返すメソッドの例
TResult ThrowingMethod(ExceptionHandler<TResult> exceptionHandler) {
//code before exception
return exceptionHandler.handle(new Exception()); //return to interrupt execution
//code after exception
}
TResult CatchingMethod() {
return ThrowingMethod(exception => */ handle exception and return value */ );
}
と
delegate TResult ExceptionHandler<TResult>(Exception exception);