例外処理 (C# プログラミング ガイド)
C# では、例外による影響を受けることがあるコードを分割するために try ブロックを使用します。 その結果発生する例外を処理するためには、これに関連付けられた catch ブロックを使用します。 また、finally ブロックには、try ブロックで例外がスローされたかどうかに関係なく実行されるコード (try ブロックで割り当てたリリースの解放など) が置かれます。 try ブロックには、関連付けられた catch ブロックと finally ブロックの少なくとも 1 つ、またはその両方が必要です。
次の例では、try-catch ステートメント、try-finally ステートメント、および try-catch-finally ステートメントについて示します。
try
{
// Code to try goes here.
}
catch (SomeSpecificException ex)
{
// Code to handle the exception goes here.
// Only catch exceptions that you know how to handle.
// Never catch base class System.Exception without
// rethrowing it at the end of the catch block.
}
try
{
// Code to try goes here.
}
finally
{
// Code to execute after the try block goes here.
}
try
{
// Code to try goes here.
}
catch (SomeSpecificException ex)
{
// Code to handle the exception goes here.
}
finally
{
// Code to execute after the try (and possibly catch) blocks
// goes here.
}
catch ブロックも finally ブロックも存在しない try ブロックは、コンパイラ エラーになります。
catch ブロック
catch ブロックでは、キャッチする例外の種類を指定できます。 種類の指定は、例外フィルターと呼ばれます。 例外の種類は、Exception から派生する必要があります。 通常、例外フィルターとして Exception は指定しません。ただし、try ブロックでスローされる例外の処理方法が判明している場合、または catch ブロックの末尾に throw ステートメントを挿入している場合を除きます。
異なる例外フィルターを持つ複数の catch ブロックを使用できます。 例外がスローされるたびに、コード内の catch ブロックが上から下に評価されますが、実行される catch ブロックは 1 つだけです。 実行されるのは、スローされた例外の種類または基本クラスを正確に指定している最初の catch ブロックです。 一致する例外フィルターを指定する catch ブロックがない場合は、フィルターを持たない catch ブロックが選択されます (そのようなブロックがステートメント内に存在する場合)。 最も限定的な (つまり、最派生の) 例外の種類を持つ catch ブロックを最初に配置することが重要です。
次の条件に当てはまる場合は、例外をキャッチする必要があります。
例外がスローされた原因を明確に把握しており、FileNotFoundException オブジェクトをキャッチしたときにユーザーに新しいファイル名の入力を求めるなど、特定の回復措置を実装できる場合。
より限定的な新しい例外を生成し、スローできる場合。
int GetInt(int[] array, int index) { try { return array[index]; } catch(System.IndexOutOfRangeException e) { throw new System.ArgumentOutOfRangeException( "Parameter index is out of range."); } }
例外を部分的に処理してから、他の処理に例外を渡すことがあります。 次の例では、例外を再スローする前にエラー ログにエントリを追加するために catch ブロックが使用されています。
try { // Try to access a resource. } catch (System.UnauthorizedAccessException e) { // Call a custom error logging procedure. LogError(e); // Re-throw the error. throw; }
finally ブロック
finally ブロックでは、try ブロックで実行されるアクションをクリーンアップできます。 finally ブロックが存在する場合、このブロックは、try ブロックと、一致した catch ブロックの後で最後に実行されます。 finally ブロックは、例外がスローされたかどうか、または例外の種類に一致する catch ブロックが見つかったかどうかとは無関係に常に実行されます。
finally ブロックを使用すると、ガベージ コレクターが実行時にオブジェクトを終了するのを待たずに、ファイル ストリーム、データベース接続、グラフィックス ハンドルなどのリソースを解放できます。 詳細については、「using ステートメント (C# リファレンス)」を参照してください。
次の例では、finally ブロックを使用して、try ブロックで開かれたファイルを閉じます。 ファイルを閉じる前に、ファイル ハンドルの状態がチェックされることに注意してください。 try ブロックでファイルを開くことができない場合でも、ファイル ハンドルの値は null のままであるため、finally ブロックでファイルを閉じようとすることはありません。 また、try ブロックで正常にファイルが開かれている場合は、finally ブロックでファイルが閉じられます。
System.IO.FileStream file = null;
System.IO.FileInfo fileinfo = new System.IO.FileInfo("C:\\file.txt");
try
{
file = fileinfo.OpenWrite();
file.WriteByte(0xF);
}
finally
{
// Check for null because OpenWrite might have failed.
if (file != null)
{
file.Close();
}
}
C# 言語仕様
詳細については、「C# 言語仕様」を参照してください。言語仕様は、C# の構文と使用法に関する信頼性のある情報源です。