[.NET]例外の再スロー(Throwの引数の有無) [Programming .NET Tips]
[ポイント]
・.NET系言語(C#、VB.NET)のプログラムコードで、
以下のような構文を見かけることがあります。
Tryステートメント内で発生した例外をCatchして、
再度スローする処理で、「Throw ex」と書く人が結構多いようですが、
実はこのような書き方をすると、
ここでCatchする以前のトレース情報が失われてしまうのです。
トレース情報を保持しつつ再スローするには、
以下の様に、「Throw ex」ではなく「Throw 」と記述します。
なぜか書籍やMSDNにも、前者の書き方でサンプルを紹介している為、
知らない人が多いようです。
(Throwステートメントとは直接関係ないサンプルだから、
あまり重要視していないのだと思いますが…)
[参考文献]
[検証]
Throwステートメントの仕様について、
2つのパターンの検証プログラムを実行して、結果を比較してみた。
・パターン1(Throwステートメントに引数がある場合)
・パターン1の実行結果(Throwステートメント[引数あり])
Throwの引数を指定した場合は、
保持されているトレース情報は、Method1、Button1_Clickのみで、
Method2、Method3、Method4は保持されていないことがわかります。
引数指定での再スローでは、それより前のトレース情報を保持しない為です。
この例では、
Method3で再スローする時に、Method4以降のトレース情報を保持しない、
Method2で再スローする時に、Method3以降のトレース情報を保持しない、
Method1で再スローする時に、Method2以降のトレース情報を保持しない為、
図のような結果になります。
・パターン2(Throwステートメント[引数なし])
・パターン2の実行結果(Throwステートメント[引数なし])
Throwの引数を指定しない場合は、
関連するトレース情報(Method1、Method2、Method3、Method4、Button1_Click)を
全て保持していることがわかります。
・.NET系言語(C#、VB.NET)のプログラムコードで、
以下のような構文を見かけることがあります。
| |
[VB.NET]例外の再スロー[Throwの引数がある場合] |
再度スローする処理で、「Throw ex」と書く人が結構多いようですが、
実はこのような書き方をすると、
ここでCatchする以前のトレース情報が失われてしまうのです。
トレース情報を保持しつつ再スローするには、
以下の様に、「Throw ex」ではなく「Throw 」と記述します。
| |
[VB.NET]例外の再スロー[Throwの引数がない場合] |
なぜか書籍やMSDNにも、前者の書き方でサンプルを紹介している為、
知らない人が多いようです。
(Throwステートメントとは直接関係ないサンプルだから、
あまり重要視していないのだと思いますが…)
[参考文献]
・「C#クックブック 第3版」 |
「レシピ4.1 キャッチした例外を再スローするタイミングを把握する」で、 Throwステートメントの引数の有無の違いを明確に説明しています。 「Throw」(引数なし)の記述を推奨しています。 |
・「プログラミングC#―C#2.0/.NET2.0/Visual Studio2005対応」 |
「11.4 例外の再スロー」で、 理由の説明はないが、「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ステートメントに引数がある場合)
| |
[VB.NET]例外[Throwの引数がある場合] |
Throwの引数を指定した場合は、
保持されているトレース情報は、Method1、Button1_Clickのみで、
Method2、Method3、Method4は保持されていないことがわかります。
引数指定での再スローでは、それより前のトレース情報を保持しない為です。
この例では、
Method3で再スローする時に、Method4以降のトレース情報を保持しない、
Method2で再スローする時に、Method3以降のトレース情報を保持しない、
Method1で再スローする時に、Method2以降のトレース情報を保持しない為、
図のような結果になります。
・パターン2(Throwステートメント[引数なし])
| |
[VB.NET]例外[Throwの引数がない場合] |
Throwの引数を指定しない場合は、
関連するトレース情報(Method1、Method2、Method3、Method4、Button1_Click)を
全て保持していることがわかります。
コメント 0