Edited at

例外フィルター

More than 3 years have passed since last update.

Visual Studio 2015 より、C# のバージョンが 6 になり、例外フィルターが追加されました。

例外フィルターは VB.net では以前より実装されていましたが、あまり使ったことが無かったので調べてみました。


VBの例外処理

文法は次のようになっています。

Try

[ tryStatements ]
[ Exit Try ]
[ Catch [ exception [ As type ] ] [ When expression ]
[ catchStatements ]
[ Exit Try ] ]
[ Catch ... ]
[ Finally
[ finallyStatements ] ]
End Try

例外フィルターとは Catch の後の When のことで Catch 節を処理するかどうかの条件を指定できます。

Catch の中で If 文により処理を分岐させるのと何が違うのか理解できていなかったので今まで使用してきませんでした。

C# で新しく例外フィルターが追加され、例外フィルターの一般的な使用方法にログの記録があると説明されています。Catch の中で例外を再スローするとスタックに影響を及ぼすそうです。

例えばログを記録して再スローする簡単な例を一つ。

Sub Main()

Try
AAA() '(1)
Catch ex As Exception
Console.WriteLine(ex)
End Try
End Sub

Sub AAA()
Try
BBB() '(2)
Catch ex As Exception
Console.WriteLine(ex.ToString())
Throw '(3)
End Try
End Sub

Sub BBB()
Try
Throw New Exception("TEST") '(4)
Catch ex As Exception
Console.WriteLine(ex.ToString())
Throw '(5)
End Try
End Sub

Main 関数でキャッチされる例外のスタックトレースには (5), (3), (1) の順に記録されています。

Catch 内でそのまま Throw していますが Throw ex のようにすると Main 関数でキャッチされる例外のスタックトレースは (3), (1) になり、BBB で発生した情報が無くなります。例外をそのまま再スローする場合は Throw の後には例外を書かないようにします。

でも、望ましいのは (4), (2), (1) が記録されているスタックトレースだと思います。例外フィルターを利用して例外処理を通らないようにすれば再スローも必要が無いので望みのスタックトレースになります、そこでログを出力して False を返す関数を When の条件に指定します。

Sub BBB()

Try
Throw New Exception("TEST")
Catch ex As Exception When ErrorLog(ex)
End Try
End Sub

Function ErrorLog(ex As Exception)
Console.WriteLine(ex.ToString())
Return False
End Function