|
|
連載
改訂版
プロフェッショナルVB.NETプログラミング
Chapter 09 例外処理
株式会社ピーデー
川俣 晶
2004/06/10 |
|
|
構造化例外処理と非構造化例外処理の混用で紹介したリスト9-9の11行目で、Throwステートメントを使用していた。これは、そのサンプル・プログラムでは実行されない部分で、形式的に入れておいただけのステートメントである。しかし、もし実行されたら、どのような効能をもたらすのだろうか?
まず、On Error GotoステートメントもTryステートメントもない状態でエラーが発生するケースを見てみよう。
1: Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
2: Dim a As Integer = 1, b As Integer = 0
3: Trace.WriteLine(a \ b)
4: End Sub
|
|
リスト9-35 On Error GotoステートメントもTryステートメントも使用していないプログラム
|
これを実行すると以下のようになる。
|
●図9-36 リスト9-35の実行結果 |
では、例外処理の中でThrowステートメントを実行するとどうなるのだろうか。リスト9-37は実際に例外処理の中でThrowステートメントが実行されるようにした例である。
1: Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
2: Dim a As Integer = 1, b As Integer = 0
3: Try
4: Trace.WriteLine(a \ b)
5: Catch ex As Exception
6: If TypeOf ex Is DivideByZeroException Then
7: Throw
8: End If
9: Trace.WriteLine(ex.Message)
10: End Try
11: End Sub
|
|
リスト9-37 例外処理の中でThrowステートメントが実行されるようにしたプログラム
|
これを実行すると以下のようになる。
|
●図9-38 リスト9-37の実行結果 |
見てのとおり、例外として0除算をキャッチしたはずなのに、まるでそれがなかったかのように同じエラー・メッセージが表示されている。Throwステートメントは、例外処理の中で使用されると、例外処理を中止して、そこでもう一度同じ例外を発生させる効能を持つ。もちろん、その時点で発生した例外は、TryステートメントとCatchブロックの中間で起きているわけではないので、再び同じCatchブロックでキャッチされることはない。
しかし、例外がネストしている場合、外側のCatchブロックがこの例外を捕まえることはできる。それを示したサンプル・ソースがリスト9-39である。
1: Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
2: Dim a As Integer = 1, b As Integer = 0
3: Try
4: Try
5: Trace.WriteLine(a \ b)
6: Catch ex As Exception
7: If TypeOf ex Is DivideByZeroException Then
8: Throw
9: End If
10: Trace.WriteLine(ex.Message)
11: End Try
12: Catch ex As DivideByZeroException
13: Trace.WriteLine("0除算をキャッチしました")
14: End Try
15: End Sub
|
|
リスト9-39 Throwステートメントによる例外をCatchブロックで捕まえるプログラム
|
これを実行すると以下のようになる。
|
リスト9-40 リスト9-39の実行結果
|
つまり、8行目で再発生させられた例外は、もはや6行目のCatchブロックにキャッチされることはないが、その外側の例外ブロック、12行目のCatchブロックにはキャッチされるということである。
この機能は、実際の例外処理を、よりネストの外側の例外ブロックに任せたいときに有効である。
VB 6では、Errorステートメントや、ErrオブジェクトのRaiseメソッドでエラーを自発的に発生させることができた。同様に、例外も、何かのエラーが起こった場合に限らず、自発的にいつでも発生させることができる。
リスト9-41は、VB 6でErrorステートメントを使用した例を示したものである。
1: Private Sub Form_Load()
2: Error 11
3: End Sub
|
|
リスト9-41 Errorステートメントによりエラーを自発的に発生させるプログラム
|
これを実行すると以下のようになる。
|
●図9-42 リスト9-41の実行結果 |
リスト9-43はRaiseメソッドを使用した例を示したものである。
1: Private Sub Form_Load()
2: Err.Raise 11
3: End Sub
|
|
リスト9-43 Raiseメソッドによりエラーを自発的に発生させるプログラム
|
これを実行すると以下のようになる。
|
●図9-44 リスト9-43の実行結果 |
さて、これと同じように、自発的に例外を発生させるVB.NETのサンプル・プログラムを以下に
1: Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
2: Throw New DivideByZeroException()
3: End Sub
|
|
リスト9-45 Throwステートメントにより自発的に例外を発生させるプログラム
|
示す(リスト9-45)。
これを実行すると以下のようになる。
|
●図9-46 リスト9-45の実行結果 |
すでに説明したThrowステートメントが再登場したが、今度は引数付きである。引数には例外オブジェクトを指定する。通常は、例外を発生させるときに新しい例外オブジェクトを作成するので、ThrowステートメントにはNewキーワードが続くことが多い。そして、発生させたい例外のクラス名を記述する。
ここで注意しておく必要があるのは、引数の有無により、Throwステートメントを記述できる場所が変わることである。引数なしのThrowステートメントは、例外の再発生という役割を持っている関係上、例外処理中でしか使用できない。しかし、引数を明示したThrowステートメントは新規の例外を発生させるので、特に例外処理中という制約はない。
さて、ErrオブジェクトのRaiseメソッドは、いくつもの引数でエラーの詳細を指定できるが、基本的に例外オブジェクトはRaiseメソッドほど多くの引数を持っていない。しかし、例外はクラスによって指定される関係上、クラスの定義次第でいくらでも引数が増える可能性がある。例えば、FileNotFoundExceptionクラス(ファイルが見つからない例外)のコンストラクタにはファイル名を指定する引数が存在する。
どの例外でも共通に使用できるのは、詳しい説明を示す文字列を付加する機能である。それを利用した例がリスト9-47である。
1: Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
2: Throw New DivideByZeroException("Throwステートメントにより発生した例外です。")
3: End Sub
|
|
リスト9-47 例外の説明を示す文字列を利用したプログラム
|
これを実行すると以下のようになる。
|
●図9-48 リスト9-47の実行結果 |
見てのとおり、単に例外を発生させるだけでなく、説明のための文字列を付加することができている。
業務アプリInsider 記事ランキング
本日
月間