連載

改訂版
プロフェッショナルVB.NETプログラミング

Chapter 09 例外処理

株式会社ピーデー 川俣 晶
2004/06/10


 本記事は、(株)技術評論社が発行する書籍『VB6プログラマーのための入門 Visual Basic .NET 独習講座』の一部分を許可を得て転載したものです。同書籍に関する詳しい情報については、本記事の最後に掲載しています。

例外の再発生

 構造化例外処理と非構造化例外処理の混用で紹介したリスト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ブロックで捕まえるプログラム

 これを実行すると以下のようになる。

1: 0除算をキャッチしました
リスト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の実行結果

 見てのとおり、単に例外を発生させるだけでなく、説明のための文字列を付加することができている。


 INDEX
  [連載] 改訂版 プロフェッショナルVB.NETプログラミング
  Chapter 09 例外処理
    1.On Error Gotoを使用した非構造化例外処理/Try〜Catchを使用した構造化例外処理
    2.構造化例外処理と非構造化例外処理の混用/On Error Resume Next/複数のエラーを扱う
    3.例外情報の活用/ネストした例外処理
  4.例外の再発生/プログラムにより明示的に例外を発生させる
    5.例外の自作/InnerExceptionについて
    6.構造化例外処理の確実な終了処理/Finallyブロックの確実性/深い階層からの例外とFinallyブロック
 
「改訂版 プロフェッショナルVB.NETプログラミング 」


Insider.NET フォーラム 新着記事
  • 第2回 簡潔なコーディングのために (2017/7/26)
     ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている
  • 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
     Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう
  • 第1回 明瞭なコーディングのために (2017/7/19)
     C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える
  • Presentation Translator (2017/7/18)
     Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)
- PR -

注目のテーマ

業務アプリInsider 記事ランキング

本日 月間
ソリューションFLASH