例外処理 (C# プログラミング ガイド)
更新 : 2007 年 11 月
C# では、例外の影響を受ける可能性があるコードを分割するために try ブロックを使用し、スローされた例外を処理するために catch ブロックを使用します。また、finally ブロックを使用すると、例外がスローされたかどうかとは無関係にコードを実行できます。例外がスローされた場合、try/catch 構成要素以降のコードは実行されないため、このブロックが必要になることがあります。try ブロックは、catch ブロックまたは finally ブロックと一緒に使用する必要があり、複数の catch ブロックを含めることができます。次に例を示します。
try
{
// Code to try here.
}
catch (SomeSpecificException ex)
{
// Code to handle exception here.
// Only catch exceptions 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 here.
}
finally
{
// Code to execute after try here.
}
try
{
// Code to try here.
}
catch (SomeSpecificException ex)
{
// Code to handle exception here.
}
finally
{
// Code to execute after try (and possibly catch) here.
}
catch ブロックも finally ブロックも存在しない try ステートメントは、コンパイラ エラーになります。
catch ブロック
catch ブロックでは、キャッチする例外の種類を指定できます。これは "例外フィルタ" と呼ばれ、Exception の派生型にする必要があります。通常は catch ブロックで Exception は指定しないでください。ただし、try ブロックでスローされる可能性のあるすべての例外を処理する特定の方法が判明している場合、または throw ステートメントを catch ブロックの末尾に挿入する場合を除きます。
異なる例外フィルタを持つ複数の 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) { LogError(e); // call a custom error logging procedure throw e; // re-throw the error }
finally ブロック
finally ブロックでは、try ブロックで実行されたアクションをクリーンアップできます。finally ブロックが存在する場合、このブロックは、try ブロックと catch ブロックの後に実行されます。finally ブロックは、例外がスローされたかどうかや、例外の型に一致する catch ブロックが検出されたかどうかとは無関係に常に実行されます。
finally ブロックを使用すると、ガベージ コレクタが実行時にオブジェクトを終了するのを待たずに、ファイル ストリーム、データベース接続、グラフィックス ハンドルなどのリソースを解放できます。詳細については、「using ステートメント (C# リファレンス)」を参照してください。
次の例では、finally ブロックを使用して、try ブロックで開かれたファイルを閉じます。ファイルを閉じる前に、ファイル ハンドルの状態がチェックされることに注意してください。try ブロックでファイルを開かなくても、ファイル ハンドルは null に設定されます。また、ファイルが正常に開かれ、例外がスローされない場合も、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# 言語仕様」の次のセクションを参照してください。
16 例外
8.9.5 throw ステートメント
8.10 try ステートメント