この章のテーマ §
try/catch/finally構文について学びます。例外処理の横取り方法と、確実な終了処理を学びます。
前提知識 §
Console.WriteLineメソッド, 文字列の基礎, 変数の基礎, メソッドの基礎, int型, 複文, 継承
解説 §
try/catch/finally構文には2つの異なる機能で構成されます。
- 例外の発生を検出するtry/catch構文
- どんな方法でもtryブロックを抜けたら実行するtry/finally構文
両者は同時に使うこともできます。
try/catch構文は、try { 文1 } catch( 例外の型名 変数名) { 文2 }と書き、文1を実行中に指定した例外が発生すると即座に文2を実行します。プログラムを止めることはありません。
try/finally構文は、try { 文1 } finally { 文2 }と書き、文1を実行中にどんな方法であろうとも文1を離脱しようとしたときに文2が実行されます。たとえば、return文でメソッドを抜ける時にも実行されます。これでリソースの後始末が確実にできます。
2つを同時に使う時はtry { 文1 } catch( 例外の型名 変数名) { 文2 }finally { 文3 }と書きます。複数の例外を待ちたいときはcatch節が複数あっても構いませんが、finallyは1つです。
罠の数々 §
- キャッチする例外の条件は、whenキーワードで更に細かく絞り込むこともできる
- 例外にも継承関係があり、ファイルが見つからないFileNotFoundExceptionは入出力例外のIOExceptionを継承しているので、IOExceptionの指定でFileNotFoundException「も」キャッチできる
- 例外の詳細は、catchの後で指定した変数に格納されている。たとえば、サンプルソースで使用しているMessageプロパティは例外の説明文が格納されている
参考リンク §
try-catch (C# リファレンス)
try-finally (C# リファレンス)
サンプルソース: kw_try §
int a = 1;
int b = 0;
Console.WriteLine("sub1を実行します。");
sub1();
Console.WriteLine("sub2を実行します。");
Console.WriteLine($"結果は{sub2()}です。");
void sub1()
{
try
{
Console.WriteLine(a / b);
}
catch (DivideByZeroException e)
{
Console.WriteLine($"例外が起きました。例外の種類は{e.Message}です。");
}
}
int sub2()
{
try
{
return a + b;
}
finally
{
Console.WriteLine("sub2の処理はこれで終わりです。");
}
}
実行結果 §
sub1を実行します。
例外が起きました。例外の種類はAttempted to divide by zero.です。
sub2を実行します。
sub2の処理はこれで終わりです。
結果は1です。
リポジトリ §
https://github.com/autumn009/CSharpPrimer2
練習問題 §
以下のプログラムの実行結果を予測してみよう。
try
{
try
{
try
{
return;
}
finally
{
Console.Write("A");
}
}
finally
{
Console.Write("B");
}
}
finally
{
Console.Write("C");
}
- A
- B
- C
- ABC
- コンパイルエラー
[[解答]]