「エラー処理(例外処理)の基本」で説明したように、Try...FinallyステートメントのFinallyブロックは、Tryブロックがどのような形で終了しても実行されます。しかし本当にそうなのか、色々なケースで実験してみました。
次のようにReturnでメソッドを抜けた場合、Finally文は実行されました。
Shared Sub FinallyTest() Try Return Finally Console.WriteLine("Finally called") End Try End Sub
static void FinallyTest() { try { return; } finally { Console.WriteLine("Finally called"); } }
Exit(break)でループを抜けた時も、Finally文は実行されました。Continueでジャンプしても、やはり実行されます。
While True Try Exit While Finally Console.WriteLine("Finally called") End Try End While
while (true) { try { break; } finally { Console.WriteLine("Finally called"); } }
GoToでジャンプしても、Finally文は実行されました。
Try GoTo Jump Finally Console.WriteLine("Finally called") End Try Jump: Console.WriteLine("Jump") '以下、出力例 'Finally called 'Jump
try { goto Jump; } finally { Console.WriteLine("Finally called"); } Jump: Console.WriteLine("Jump"); //以下、出力例 //Finally called //Jump
Windowsアプリケーションにおいて、Tryブロック内でフォームを閉じてプログラムを終了した時もFinally文は実行されました。Application.ExitメソッドやApplication.ExitThreadメソッドで終了した時も、実行されます。
Try Me.Close() Finally Console.WriteLine("Finally called") End Try
try { this.Close(); } finally { Console.WriteLine("Finally called"); }
次のようにEnvironment.Exitメソッドでアプリケーションを終了した時は、Finallyが実行されませんでした。
VB.NETのEndステートメントはEnvironment.Exitメソッドと同じですので、やはりFinallyは実行されません。
Try Environment.Exit(0) Finally Console.WriteLine("Finally called") End Try
try { Environment.Exit(0); } finally { Console.WriteLine("Finally called"); }
.NET Framework 2.0で追加されたEnvironment.FailFastメソッドは、MSDNの説明にある通り、Finallyを実行せずにプロセスを終了させます。
Try Environment.FailFast("テストです。") Finally Console.WriteLine("Finally called") End Try
try { Environment.FailFast("テストです。"); } finally { Console.WriteLine("Finally called"); }
今度は別スレッド(バックグラウンドスレッド)で実行した時の例です。この場合スレッドをAbortメソッドで中断するとFinally文は実行されます。しかし、スレッド実行中にアプリケーションを終了させた場合は、Finally文は実行されませんでした。
Private t As System.Threading.Thread 'Button1のClickイベントハンドラ Private Sub Button1_Click(sender As Object, e As System.EventArgs) _ Handles Button1.Click 'スレッド開始 t = New System.Threading.Thread( _ New System.Threading.ThreadStart(AddressOf thread1)) t.IsBackground = True t.Start() End Sub Private Sub thread1() Try '無限ループ While True End While Finally Console.WriteLine("Finally called") End Try End Sub 'Button2のClickイベントハンドラ Private Sub Button2_Click(sender As Object, e As System.EventArgs) _ Handles Button1.Click 'スレッド終了 t.Abort() End Sub 'Button3のClickイベントハンドラ Private Sub Button3_Click(sender As Object, e As EventArgs) _ Handles Button1.Click 'アプリケーション終了 Application.Exit() End Sub
System.Threading.Thread t; //Button1のClickイベントハンドラ private void Button1_Click(object sender, System.EventArgs e) { //スレッド開始 t = new System.Threading.Thread(new System.Threading.ThreadStart(thread1)); t.IsBackground = true; t.Start(); } private void thread1() { try { //無限ループ for (; ; ) { } } finally { Console.WriteLine("Finally called"); } } //Button2のClickイベントハンドラ private void Button2_Click(object sender, System.EventArgs e) { //スレッド終了 t.Abort(); } //Button3のClickイベントハンドラ private void Button3_Click(object sender, EventArgs e) { //アプリケーション終了 Application.Exit(); }
Finallyブロックは、ほとんどの場合、実行されます。ただし、以下のような場合は実行されません。