例外処理 (C# プログラミング ガイド)
try ブロックは、例外の影響を受ける可能性があるコードを区分化するために、 C# プログラマによって使用されます。 関連付けられた catch ブロックは、スローされた例外を処理するために使用されます。 finally ブロックには、try
ブロックで例外がスローされたかどうかにかかわらず実行されるコードが含まれます (try
ブロックに割り当てられたリソースの解放など)。 try
ブロックには、1 つ以上の catch
ブロック、finally
ブロック、またはその両方が関連付けられる必要があります。
次のコードは、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.
}
try
ブロックに catch
または finally
ブロックがない場合は、コンパイル エラーが発生します。
catch ブロック
catch
ブロックでは、キャッチする例外の種類を指定できます。 この型指定は、例外フィルターと呼ばれます。 例外の種類は、Exception から派生している必要があります。 一般に、try
ブロックからスローされる可能性があるすべての例外の処理方法を把握している場合や、catch
ブロックの末尾に throw
ステートメントが含まれている場合を除いては、例外フィルターとして Exception を指定しないでください。
複数の catch
ブロックに異なる例外クラスが含まれている場合は、それらを連結することができます。 catch
ブロックはコード内で上から下に評価されますが、スローされた各例外に対して実行される catch
ブロックは 1 つだけです。 スローされた例外の厳密な型か、その基底クラスを指定する最初の catch
ブロックが実行されます。 一致する例外クラスを指定した catch
ブロックがない場合は、種類のない catch
ブロックが選択されます (それがステートメント内に存在する場合)。 最初に配置する catch
ブロックでは、最も具体的な (つまり、最も派生した) 例外クラスを指定することが重要です。
次の条件に該当する場合は、例外をキャッチします。
- 例外がスローされる理由を十分に理解していて、かつ特定の回復手段を実装できる (FileNotFoundException オブジェクトをキャッチした場合に、ユーザーに新しいファイル名を入力するよう求めるなど)。
- より具体的な例外を新規に作成し、スローできる。
int GetInt(int[] array, int index) { try { return array[index]; } catch (IndexOutOfRangeException e) { throw new ArgumentOutOfRangeException( "Parameter index is out of range.", e); } }
- 例外を部分的に処理してから、さらに処理するために渡す必要がある。 次の例では、例外を再スローする前に、エラー ログにエントリを追加する目的で
catch
ブロックが使用されています。try { // Try to access a resource. } catch (UnauthorizedAccessException e) { // Call a custom error logging procedure. LogError(e); // Re-throw the error. throw; }
"例外フィルター" を指定して、catch 句にブール式を追加することもできます。 例外フィルターは、特定の catch 句が、その条件が true の場合にのみ一致することを示します。 次の例では、両方の catch 句で同じ例外クラスが使用されますが、追加の条件が確認され、別のエラー メッセージが作成されます。
int GetInt(int[] array, int index)
{
try
{
return array[index];
}
catch (IndexOutOfRangeException e) when (index < 0)
{
throw new ArgumentOutOfRangeException(
"Parameter index cannot be negative.", e);
}
catch (IndexOutOfRangeException e)
{
throw new ArgumentOutOfRangeException(
"Parameter index cannot be greater than the array size.", e);
}
}
常に false
を返す例外フィルターを使用すると、すべての例外を検証できますが、処理は行われません。 通常は、例外をログに記録するために使用します。
public class ExceptionFilter
{
public static void Main()
{
try
{
string? s = null;
Console.WriteLine(s.Length);
}
catch (Exception e) when (LogException(e))
{
}
Console.WriteLine("Exception must have been handled");
}
private static bool LogException(Exception e)
{
Console.WriteLine($"\tIn the log routine. Caught {e.GetType()}");
Console.WriteLine($"\tMessage: {e.Message}");
return false;
}
}
LogException
メソッドにより常に false
が返され、この例外フィルターを使用する catch
句は一致しません。 catch 句は一般的なもので (System.Exception を使用)、後の句によってより具体的な例外クラスを処理することができます。
Finally ブロック
finally
ブロックでは、try
ブロックで実行されるアクションをクリーンアップすることができます。 finally
ブロック (存在する場合) は、最後 (try
ブロックおよび一致する catch
ブロックの後) に実行されます。 finally
ブロックは、例外がスローされたかどうか、または例外の種類に一致する catch
ブロックが見つかったかどうかにかかわらず、常に実行されます。
finally
ブロックは、ランタイム内のガベージ コレクターによってオブジェクトがファイナライズされるのを待つことなく、ファイル ストリーム、データベース接続、グラフィックス ハンドルなどのリソースを解放するために使用できます。
次の例では、try
ブロックで開かれたファイルを閉じるために finally
ブロックが使用されています。 ファイルを閉じる前に、ファイル ハンドルの状態が確認されています。 try
ブロックからファイルを開けなかった場合は、ファイル ハンドルの値が null
のままになり、finally
ブロックでファイルが閉じられることはありません。 代わりに、try
ブロックでファイルが正常に開かれた場合は、finally
ブロックによって開かれたファイルが閉じられます。
FileStream? file = null;
FileInfo fileinfo = new System.IO.FileInfo("./file.txt");
try
{
file = fileinfo.OpenWrite();
file.WriteByte(0xF);
}
finally
{
// Check for null because OpenWrite might have failed.
file?.Close();
}
C# 言語仕様
詳細については、「C# 言語仕様」の例外と try ステートメントに関するセクションを参照してください。 言語仕様は、C# の構文と使用法に関する信頼性のある情報源です。
関連項目
.NET