[はじめに]
・.NET系言語(C#、VB.NET)のプログラムコードで、
以下のような構文を見かけることがあります。
|
Try
Dim x As Integer = func2(a)
Return x
Catch ex As Exception
'何らかの例外後の後処理をして、再スロー
'(例外後の処理は割愛)...
Throw ex '←ここに注目
End Try | |
[VB.NET]例外の再スロー[Throwの引数がある場合] |
Tryステートメント内で発生した例外をCatchして、
再度スローする処理で、「Throw ex」と書く人が結構多いようですが、
実はこのような書き方をすると、
ここでCatchする以前のトレース情報が失われてしまうのです。
トレース情報を保持しつつ再スローするには、
以下の様に、「Throw ex」ではなく「Throw 」と記述します。
|
Try
Dim x As Integer = func2(a)
Return x
Catch ex As Exception
'何らかの例外後の後処理をして、再スロー
'(例外後の処理は割愛)...
Throw '←exは省略します。
End Try | |
[VB.NET]例外の再スロー[Throwの引数がない場合] |
なぜか書籍やMSDNにも、前者の書き方でサンプルを紹介している為、
知らない人が多いようです。
(Throwステートメントとは直接関係ないサンプルだから、
あまり重要視していないのだと思いますが…)
[参考文献]
[検証]
Throwステートメントの仕様について、
2つのパターンの検証プログラムを実行して、結果を比較してみた。
パターン1 |
Throwステートメントに引数がある場合、
Button1_Click()→Method1()→Method2()→Method3()→Method4()と
メソッドを呼び、最下層のMethod4()で
ゼロ除算の例外(System.DevideByZeroException)を意図的に発生させる。
各々のメソッドのCatch句では、「Throw ex」(引数あり)で例外を再Throwする。
最上位メソッドにて、例外の内容(ToString()した結果)を表示する。
|
パターン2 |
Throwステートメントに引数がない場合、
Button1_Click()→Method1()→Method2()→Method3()→Method4()と
メソッドを呼び、最下層のMethod4()で
ゼロ除算の例外(System.DevideByZeroException)を意図的に発生させる。
各々のメソッドのCatch句では、「Throw 」(引数なし)で例外を再Throwする。
最上位メソッドにて、例外の内容(ToString()した結果)を表示する。
|
・パターン1(Throwステートメントに引数がある場合)
|
Private Sub Button1_Click( _
ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button1.Click
Dim num As Integer
Try
num = Method1(1, 0)
Catch ex As Exception
MessageBox.Show( _
ex.ToString(), _
"例外[Throwの引数がある場合]")
End Try
End Sub
Private Function Method1( _
ByVal a As Integer, _
ByVal b As Integer) As Integer
Try
Return Method2(a, b)
Catch ex As Exception
Throw ex
End Try
End Function
Private Function Method2( _
ByVal a As Integer, _
ByVal b As Integer) As Integer
Try
Return Method3(a, b)
Catch ex As Exception
Throw ex
End Try
End Function
Private Function Method3( _
ByVal a As Integer, _
ByVal b As Integer) As Integer
Try
Return Method4(a, b)
Catch ex As Exception
Throw ex
End Try
End Function
Private Function Method4( _
ByVal a As Integer, _
ByVal b As Integer) As Integer
Try
'b=0の時に例外が発生する。
Return a \ b
Catch ex As Exception
Throw ex
End Try
End Function
| |
[VB.NET]例外[Throwの引数がある場合] |
・パターン1の実行結果(Throwステートメント[引数あり])
Throwの引数を指定した場合は、
保持されているトレース情報は、Method1、Button1_Clickのみで、
Method2、Method3、Method4は保持されていないことがわかります。
引数指定での再スローでは、それより前のトレース情報を保持しない為です。
この例では、
Method3で再スローする時に、Method4以降のトレース情報を保持しない、
Method2で再スローする時に、Method3以降のトレース情報を保持しない、
Method1で再スローする時に、Method2以降のトレース情報を保持しない為、
図のような結果になります。
・パターン2(Throwステートメント[引数なし])
|
Private Sub Button1_Click( _
ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button1.Click
Dim num As Integer
Try
num = Method1(1, 0)
Catch ex As Exception
MessageBox.Show( _
ex.ToString(), _
"例外[Throwの引数がない場合]")
End Try
End Sub
Private Function Method1( _
ByVal a As Integer, _
ByVal b As Integer) As Integer
Try
Return Method2(a, b)
Catch ex As Exception
Throw
End Try
End Function
Private Function Method2( _
ByVal a As Integer, _
ByVal b As Integer) As Integer
Try
Return Method3(a, b)
Catch ex As Exception
Throw
End Try
End Function
Private Function Method3( _
ByVal a As Integer, _
ByVal b As Integer) As Integer
Try
Return Method4(a, b)
Catch ex As Exception
Throw
End Try
End Function
Private Function Method4( _
ByVal a As Integer, _
ByVal b As Integer) As Integer
Try
'b=0の時に例外が発生する。
Return a \ b
Catch ex As Exception
Throw
End Try
End Function | |
[VB.NET]例外[Throwの引数がない場合] |
・パターン2の実行結果(Throwステートメント[引数なし])
Throwの引数を指定しない場合は、
関連するトレース情報(Method1、Method2、Method3、Method4、Button1_Click)を
全て保持していることがわかります。
0 件のコメント:
コメントを投稿