例外の概要
例外とは、実行プログラムが遭遇するエラー状態や予期しない動作のことです。例外が発生する原因には、作成したコードや呼び出したコード (共有ライブラリなど) での違反、オペレーティング システム リソースが使用できない状況、共通言語ランタイムにより検出された予期しない状況 (たとえば、コードを検証できない) などがあります。このようなエラーには、アプリケーションによって回復できるエラーと、回復できないエラーがあります。ほとんどのアプリケーション例外からは回復できますが、ほとんどのランタイム例外からは回復できません。
.NET Framework では、例外は Exception クラスの継承オブジェクトです。例外は、問題が発生したコード領域からスローされます。アプリケーションが例外を処理するか、またはプログラムが終了するまで、例外はスタックに渡されます。.NET Framework を使用した例外処理の詳細については、Exception クラスのトピックを参照してください。
ランタイムによる例外の管理
ランタイムは、例外オブジェクトとプロテクト ブロック コードに基づいた例外処理モデルを使用しています。例外が発生すると、その例外を表す Exception オブジェクトが作成されます。
ランタイムにより、各実行可能ファイルに対して例外情報テーブルが作成されます。実行可能ファイルの各メソッドに対して、例外情報テーブルの例外処理情報配列が関連付けられます。この配列は空のこともあります。配列の各エントリは、プロテクト ブロック コード、コードに関連付けられている例外フィルタ、および例外ハンドラ (catch ステートメント) を記述します。例外テーブルは非常に効率的な機能であり、例外が発生しない状況では、プロセッサ時間やメモリの使用量などパフォーマンスへの影響はありません。例外が発生した場合だけにこれらのリソースが使用されます。
例外情報テーブルに示されるプロテクト ブロックに対する 4 種類の例外ハンドラを次に示します。
finally ハンドラ。このハンドラは、通常の制御フローまたは未処理の例外によってブロックが終了するたびに実行されます。
フォールト ハンドラ。このハンドラは、例外が発生した場合に実行されます。通常の制御フロー完了時には実行されません。
タイプ フィルタ ハンドラ。このハンドラは、指定されているクラスまたはその派生クラスの例外をすべて処理します。
ユーザー フィルタ ハンドラ。このハンドラは、関連付けられているハンドラで例外を処理するか、または次のプロテクト ブロックに例外を渡すかどうかを判別するために、ユーザーが指定したコードを実行します。
各言語では、言語の仕様に従って上記の例外ハンドラが実装されます。たとえば、Visual Basic 2005 では、catch ステートメントの When キーワードを使用した変数比較によって、ユーザー フィルタ ハンドラへのアクセスを実現します。C# では、ユーザー フィルタ ハンドラは実装されません。
例外が発生すると、ランタイムは次の 2 段階の処理を実行します。
次の 2 つの条件に一致する 1 番目のプロテクト ブロックの配列を検索します。
現在実行中の命令が含まれている領域を保護している。
例外ハンドラ、または例外を処理するフィルタのいずれかが含まれている。
上記の条件に一致するブロックの配列が検出されると、ランタイムは例外を記述する Exception オブジェクトを作成します。ランタイムは次に、例外が発生したステートメントと例外を処理するステートメントの間にある finally ステートメントと fault ステートメントをすべて実行します。例外ハンドラの順序は重要です。最も内側の例外ハンドラが最初に評価されます。また、例外ハンドラは例外をキャッチするルーチンのローカル変数とローカル メモリへアクセスできますが、例外がスローされた時点の中間値はすべて失われることにも注意してください。
現在のメソッドで一致するブロックが検出されないと、ランタイムはスタック内で現在のメソッドの呼び出し元を 1 つずつ検索します。どの呼び出し元にも一致するブロックがない場合には、デバッガが例外へアクセスできます。デバッガが例外にアタッチされていない場合には、UnhandledException イベントが発生します。UnhandledException イベントのリスナがない場合、ランタイムはスタック トレースをダンプし、プログラムを終了します。
ランタイム例外のフィルタ処理
キャッチする例外や処理する例外を、例外の種類やユーザー定義条件に従ってフィルタ処理できます。
タイプ フィルタ ハンドラは、特定の種類の例外 (またはこの例外から派生したクラス) を処理します。最も一般的なタイプ フィルタ例外ハンドラでは、1 つのクラスの例外だけがキャッチされることが指定されます。
特定の例外をキャッチする例外ハンドラを次のコード例に示します。このコード例では、FileNotFoundException がキャッチされます。
Catch e As FileNotFoundException
Console.WriteLine("[Data File Missing] {0}", e)
catch(FileNotFoundException e) {
Console.WriteLine("[Data File Missing] {0}", e);
}
ユーザー フィルタ例外ハンドラは、独自に定義された例外の条件に基づいて例外をキャッチおよび処理します。Visual Basic 2005 の場合、これらのハンドラでは Catch ステートメントを When キーワードで使用します。この例外フィルタ処理の詳細については、「catch ブロックでの特定の例外の使用」を参照してください。
参照
概念
Exception クラスとプロパティ
例外階層
例外処理の実施