私の理解は、C# 仕様に記載されている動作をサポートするこの長いが素晴らしい記事に基づいています。
CLI 標準 (EMCA-335) は、適切なキャッチがない場合、ランタイムはすぐに終了する必要があることを示しています。.NET ランタイムはこれを行いません。代わりに、C# 仕様 (EMCA-334) の動作に傾いているようです。
まず、言語仕様がフレームワークの動作を定義しているように見えるのは奇妙だと思います。第二に、彼らは矛盾しているようです。
- それらは互いに矛盾していますか、それともドキュメントの意味を間違っていますか?
- ランタイムは、標準に準拠するためにこの方法で例外処理を行う必要がありますか?
オプションの質問として、どれが「正しい」ものであるか、つまり、CLI の独自の実装を作成する場合、どれを使用すればよいですか? EMCA-335 (CLI) ドキュメントは 2 か月前に更新され、EMCA-334 (C#) は 2006 年に更新されたことに注意してください。
ECMA-335 パーティション I セクション 12.4.2.5
- 例外が発生すると、CLI はアレイ内で最初の保護ブロックを検索します。
- 現在の命令ポインターを含む領域を保護し、
- キャッチ ハンドラ ブロックであり、
- 例外を処理するフィルター
現在のメソッドで一致が見つからない場合は、呼び出し元のメソッドが検索されます。一致するものが見つからない場合、CLI はスタック トレースをダンプし、プログラムを中止します。
一致が見つかった場合、CLI はスタックを直前のポイントに戻しますが、今回は finally ハンドラーと fault ハンドラーを呼び出します。次に、対応する例外ハンドラを開始します。
C# 仕様 §15.9.5 および §15.10 ( MSDN の §8.9.5 および §8.10 )
それと CLI 標準との主な違いは、catch ブロックが見つかったかどうかにかかわらず、アプリケーションは存在するだけでなく、スタックをアンワインドし、finally ハンドラーを処理することです。
以下は非常に大まかな要約であるため、これをよりよく理解するために標準自体を読むことをお勧めします。考えられる各シナリオで try ステートメントを実行する方法を段階的に概説します。
- 例外を発生させる関数で:
- 各 try ステートメントで一致する catch 句を探します
- 存在する場合は catch ステートメントを実行します
- finally ブロックが存在する場合は実行されます
- ハンドラーが存在しない場合は、呼び出し元の関数で上記の手順が繰り返されます。
- 例外処理が現在のスレッドのすべての関数メンバー呼び出しを終了し、スレッドに例外のハンドラーがないことを示す場合、スレッド自体が終了します。このような終了の影響は実装定義です。