連載

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

第15回 高度な例外処理

(株)ピーデー
川俣 晶
2002/08/31

Page1 Page2 Page3

例外の再発生

 前回の「構造化例外処理と非構造化例外処理の混用」にあるサンプル・プログラム5の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
On Error Goto文もTry文も使用していないVB.NETのサンプル・プログラム9

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

サンプル・プログラム9の実行結果

 では例外処理の中で、Throw文を実行するとどうなるだろうか。以下は実際に例外処理の中で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
例外処理の中でThrow文が実行されるようにしたVB.NETのサンプル・プログラム10

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

サンプル・プログラム10の実行結果

 見てのとおり、例外として0除算をキャッチしたはずなのに、まるでそれがなかったかのように同じエラーメッセージが表示されている。Throw文は、例外処理の中で使用されると、例外処理を中止して、そこでもう1度同じ例外を発生させる効能を持つ。もちろん、その時点で発生した例外は、Try文とCatch文の中間で起きているわけではないので、再び同じCatch文でキャッチされることはない。

 しかし、例外がネストしている場合、外側のCatch文がこの例外を捕まえることはできる。以下はそのことを示したサンプル・ソースである。

  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
Throw文による例外をCatch文で捕まえているVB.NETのサンプル・プログラム11

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

 1: 0除算をキャッチしました
サンプル・プログラム11の実行結果

 つまり、8行目で再発生させられた例外は、もはや6行目のCatch文にキャッチされることはないが、その外側の例外ブロック、12行目のCatch文にはキャッチされるということである。

 この機能は、実際の例外処理を、よりネストの外側の例外ブロックに任せたいときに有益である。

ユーザーが自ら発生させる例外

 例外は、何かのエラーが起こった場合に限らず、自発的にいつでも発生させることができる。VB 6では、Error文や、ErrオブジェクトのRaiseメソッドでエラーを自発的に発生させることができた。以下はError文を使用した例を示したものである。

 1: Private Sub Form_Load()
 2:   Error 11
 3: End Sub
Error文によりエラーを自発的に発生させるVB 6のサンプル・プログラム12

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

サンプル・プログラム12の実行結果

 以下はRaiseメソッドを使用した例を示したものである。

 1: Private Sub Form_Load()
 2:   Err.Raise 11
 3: End Sub
Raiseメソッドによりエラーを自発的に発生させるVB 6のサンプル・プログラム13

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

サンプル・プログラム13の実行結果

 さて、これと同じように、自発的に例外を発生させる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
Throw文により自発的に例外を発生させるVB.NETのサンプル・プログラム14

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

サンプル・プログラム14の実行結果

 すでに説明したThrow文が再登場したが、今度は引数付きである。引数には例外オブジェクトを指定する。通常は、例外を発生させるときに新しい例外オブジェクトを作成するので、Throw文にはNewキーワードが続くことが多い。そして、発生させたい例外のクラス名を記述する。

 ここで注意しておく必要があるのは、引数の有無により、Throw文に出番が変わることである。引数なしのThrow文は例外の再発生という役割を持っている関係上、例外処理中でしか使用できない。しかし、引数を明示したThrow文は新規の例外を発生させるので、特に例外処理中という制約はない。

 さて、ErrオブジェクトのRaiseメソッドは、いくつもの引数でエラーの詳細を指定できるが、基本的に例外オブジェクトはRaiseメソッドほど多くの引数を持っていない。しかし、例外はクラスによって指定される関係上、クラスの定義次第でいくらでも引数が増える可能性がある。例えば、FileNotFoundExceptionクラス(ファイルが見付からない例外)のコンストラクタにはファイル名を指定する引数が存在する。

 どの例外でも共通に使用できるのは、詳しい説明を示す文字列を付加する機能である。以下はそれを利用した例である。

 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
例外の説明を示す文字列を利用したVB.NETのサンプル・プログラム15

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

サンプル・プログラム15の実行結果

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

次回予告

 次回も例外処理について残された解説を続けることを予定している。例外処理は、スマートでエラーに強いプログラムを記述するために重要な機能である。がんばってマスターしよう。End of Article


 INDEX
  連載 プロフェッショナルVB.NETプログラミング
  第15回 高度な例外処理
    1.例外情報の活用
    2.ネストした例外処理
  3.例外の再発生
 
「プロフェッショナル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メールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

Insider.NET 記事ランキング

本日 月間