連載
プロフェッショナルVB.NETプログラミング
第16回 例外処理を極める
(株)ピーデー
川俣 晶
2002/09/07
|
![](../index/vb6nettitle_m.jpg) |
Finally文の確実性
Tryブロック内で使用するFinally文についてはすでに説明した。では、これはどの程度確実に動作するものなのだろうか。果たして、無条件に頼ってよいものなのだろうか? それを確認するために以下のようなサンプル・プログラムを記述してみた。これはさまざまなケースで、Finally文を使用してみたものだ。
1: Private Sub test1()
2: Try
3: Exit Sub
4: Finally
5: Trace.WriteLine("Finally called in test1")
6: End Try
7: End Sub
8:
9: Private Sub test2()
10: Do
11: Try
12: Exit Do
13: Finally
14: Trace.WriteLine("Finally called in test2")
15: End Try
16: Loop
17: End Sub
18:
19: Private Sub test3()
20: Try
21: Do
22: Exit Do
23: Loop
24: Finally
25: Trace.WriteLine("Finally called in test3")
26: End Try
27: End Sub
28:
29: Private Sub test4()
30: Try
31: Dim i As Integer
32: For i = 0 To 9
33: If i = 5 Then
34: Try
35: Exit Sub
36: Finally
37: Trace.WriteLine("Finally called in test4A")
38: End Try
39: End If
40: Next
41: Finally
42: Trace.WriteLine("Finally called in test4B")
43: End Try
44: End Sub
45:
46: Private Sub test5()
47: Try
48: While True
49: Do
50: Do
51: Exit While
52: Loop
53: Loop
54: End While
55: Finally
56: Trace.WriteLine("Finally called in test5")
57: End Try
58: End Sub
59:
60: Private Sub test6()
61: Try
62: Do
63: Do
64: Do
65: Throw New Exception("Sample")
66: Loop
67: Loop
68: Loop
69: Catch ex As Exception
70: Trace.WriteLine("Catch called in test6")
71: Finally
72: Trace.WriteLine("Finally called in test6")
73: End Try
74: End Sub
75:
76: Private Sub test7()
77: Try
78: '何もない
79: Finally
80: Trace.WriteLine("Finally called in test7")
81: End Try
82: End Sub
83:
84: Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
85: test1()
86: test2()
87: test3()
88: test4()
89: test5()
90: test6()
91: test7()
92: End Sub
|
|
さまざまなケースでのFinally文の動作を検証するVB.NETのサンプル・プログラム7 |
これを実行すると以下のようになる。
1: Finally called in test1
2: Finally called in test2
3: Finally called in test3
4: Finally called in test4A
5: Finally called in test4B
6: Finally called in test5
7: Catch called in test6
8: Finally called in test6
9: Finally called in test7
|
|
サンプル・プログラム7の実行結果 |
1〜7行目のコードは、いきなりメソッドから抜け出した場合である。実行結果を見ると5行目が実行されることが分かると思う。
9〜17行目は繰り返しの途中から脱出する場合である。実行結果を見ると14行目が実行されることが分かると思う。
19〜27行目は繰り返しの途中から脱出だが、Tryブロックがループの外側にある点が異なる。実行結果を見ると25行目が実行されることが分かると思う。脱出する個所がTryブロックの中でありさえすれば、Tryブロックを記述する場所に関係なく、Finally文が実行される。
29〜44行目はTryブロックが2重にネストしていて、どちらにもFinally文が存在する場合である。実行結果を見ると37行目も42行目も、両方とも実行されることが分かると思う。複数のTryブロックがネストして複数のFinally文が存在する場合、それらはすべて実行される。そのため、上位あるいは下位のTryブロックにすでにFinally文が存在するかどうか、気にする必要はない。書けば実行される。
46〜58行目は繰り返しがネストした途中から脱出する場合である。実行結果を見ると56行目が実行されることが分かると思う。ネストの深さはFinally文の実行とは関係ない。
60〜74行目は繰り返しの途中から例外が発生した場合である。実行結果を見ると70行目と72行目が実行されることが分かると思う。深いネスト状態から例外が起きても、Finally文は確実に実行される。
76〜82行目は何も問題なくTryブロックの実行を終える場合である。実行結果を見ると80行目が実行されることが分かると思う。途中脱出や例外の発生がなくても、Finally文はTryブロックから抜ける際に実行される。
深い階層からの例外とFinally文
Finally文の動作を確認するために、もう1つサンプル・プログラムを記述してみた。このサンプル・プログラムは、メソッド呼び出しが何重にも行っていて、その内部で例外を発生させている。
1: Private Sub test1()
2: Dim i As Integer, j As Integer
3: Trace.WriteLine(i \ j)
4: End Sub
5:
6: Private Sub test2()
7: Try
8: test1()
9: Finally
10: Trace.WriteLine("Finally called in test2")
11: End Try
12: End Sub
13:
14: Private Sub test3()
15: Try
16: test2()
17: Finally
18: Trace.WriteLine("Finally called in test3")
19: End Try
20: End Sub
21:
22: Private Sub test4()
23: Try
24: test3()
25: Finally
26: Trace.WriteLine("Finally called in test4")
27: End Try
28: End Sub
29:
30: Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
31: Try
32: test4()
33: Catch ex As DivideByZeroException
34: Trace.WriteLine("ゼロ除算が発生しました。")
35: End Try
36: End Sub
|
|
深い階層で発生した例外に対するFinally文の動作を検証するVB.NETのサンプル・プログラム8 |
これを実行すると以下のようになる。
1: Finally called in test2
2: Finally called in test3
3: Finally called in test4
4: ゼロ除算が発生しました。
|
|
サンプル・プログラム8の実行結果 |
このプログラムは、test1メソッドで例外が発生し、Form1_Loadメソッドでその例外をキャッチしている。そこでポイントになるのは、その中間に位置するtest2〜4メソッドに含まれるFinally文である。例外をキャッチするTryブロックは、Form1_Loadメソッド内にあるが、それではこの例外をキャッチしないTryブロックを持つtest2〜4メソッドに含まれるFinally文はどうなるだろうか。
結果を見て分かるとおり、すべてのFinally文に続くコードが実行されている。Finally文は、そのTryブロックでキャッチするか否かを問わず、すべて有効である。
次回予告
次回は名前空間に関する解説を予定している。![End of Article](/fdotnet/images/icon_end.gif)
Insider.NET 記事ランキング
本日
月間