« [.NET] 例外を Throw しなおすときは、 例外を付けてはいけない ( その1 ) | トップページ | [.NET] 例外を Throw しなおすときは、 例外を付けてはいけない ( その3 ) »

2008年3月21日 (金)

[.NET] 例外を Throw しなおすときは、 例外を付けてはいけない ( その2 )

Visual Studio のコード分析で警告される CA2200 "Rethrow to preserve stack details" についての、 続きです。 ( その1 は、  こちら )

実際にサンプルコードで説明していきます。


◆ 例外を出すメソッド ( 呼び出される側 )

Module Module2

    Public Function Calc1(ByVal x As Integer, ByVal y As Integer) As Integer

        Dim result As Integer = x / y   '5行目
        Return result
    End Function

End Module

このメソッドに y = 0 を渡すと、 5行目で例外が発生します。
その例外が出た時に、 例外の発生元はここであるとすぐに分かるかどうかで、 デバッグの難易度が違ってくるでしょう。

このメソッドを呼び出すコードを何種類か示します。
着目すべき点は、 バグが発覚したとき ( 例外が出た時 ) に、 このメソッド Module2 の 5行目にたどりつけるかどうか、 です。


◆ 呼び出す側のメソッド・その1 ( Try ~ Catch 無し )

Public Class Class1

    Public Shared Sub Method1()

        Dim x As Integer
        Dim y As Integer
        Dim result As Integer

        x = 10
        result = Module2.Calc1(x, y)  '10行目

    End Sub

End Class

10行目で、 y に値を設定しないまま ( 0 のまま )、 上記の Module2.Calc1() メソッドを呼び出しています。
メイン関数から、 この Method1() を呼び出すと、 例外が発生し次のようなスタックトレースが報告されます。

OverflowException occured in Class1:
   at ThrowVsThrowEx.Module2.Calc1(Int32 x, Int32 y) in E:\sample\ThrowVsThrowEx\ThrowVsThrowEx\Module2.vb:line 5
   at ThrowVsThrowEx.Class1.Method1() in E:\sample\ThrowVsThrowEx\ThrowVsThrowEx\Class1.vb:line 10
   at ThrowVsThrowEx.Module1.Main() in E:\sample\ThrowVsThrowEx\ThrowVsThrowEx\Module1.vb:line 5

問題の Module2 の5行目が、 きちんと報告されています。 呼び出す側の Class1 10行目も出ています。


◆ 呼び出す側のメソッド・その2 ( Catch して Throw Ex )
では、 Catch した上で、 その例外オブジェクトを指定して Throw する ( rethrow する ) と、 どうなるでしょう。

Public Class Class2

    Public Shared Sub Method1()
        Try
            Dim x As Integer
            Dim y As Integer
            Dim result As Integer

            x = 10
            result = Module2.Calc1(x, y)  '10行目

        Catch ex As Exception

            Throw ex    '15行目

        Finally
            Console.WriteLine("* The Finally phrase was excuted in Class2")
        End Try

    End Sub

End Class

同じく、 メイン関数から呼び出した時の出力です。 ( Finally 句の出力も出ています。 )

* The Finally phrase was excuted in Class2
OverflowException occured in Class2:
   at ThrowVsThrowEx.Class2.Method1() in E:\sample\ThrowVsThrowEx\ThrowVsThrowEx\Class2.vb:line 15
   at ThrowVsThrowEx.Module1.Main() in E:\sample\ThrowVsThrowEx\ThrowVsThrowEx\Module1.vb:line 14

報告されているのは、 Throw ex している行だけです。 本当に例外を出している Module2 の 5行目は報告されていません。 ( これが、 MSDN Library に書いてある 「スタックトレースは現在のメソッドで再開され、 例外をスローした元のメソッドと現在のメソッドの間で呼び出されたメソッドの一覧は失われます。」 ということです。 )
このくらいシンプルなコードだと、 例外を出している場所の見当は付けられると思いますが、 もっと複雑なコードの場合はどうでしょう?

# その3 ( 最終回 ) へと続く… f(^^;

|

« [.NET] 例外を Throw しなおすときは、 例外を付けてはいけない ( その1 ) | トップページ | [.NET] 例外を Throw しなおすときは、 例外を付けてはいけない ( その3 ) »

プログラミング」カテゴリの記事

コメント

コメントを書く



(ウェブ上には掲載しません)


コメントは記事投稿者が公開するまで表示されません。



トラックバック

この記事のトラックバックURL:
http://app.cocolog-nifty.com/t/trackback/209349/40588989

この記事へのトラックバック一覧です: [.NET] 例外を Throw しなおすときは、 例外を付けてはいけない ( その2 ):

« [.NET] 例外を Throw しなおすときは、 例外を付けてはいけない ( その1 ) | トップページ | [.NET] 例外を Throw しなおすときは、 例外を付けてはいけない ( その3 ) »