.NET Framework2.0の例外処理でいろいろと実験してみる。
というのも、VB6のOn Error Gotoの動きはばっちり理解しているけど、Javaから来ているTry?Catchの例外処理の動きがいまいち把握出来ていない。
これが把握できてないと、.NETでどういう例外処理を施せばいいのかがわからない。
VB6の場合は、戻り値をStringにして、エラーメッセージを積み重ねていって、疑似スタックトレースなんてものを作ったりした。
On Error Gotoの仕組みは、うっかりしたことでエラー情報が消失したりして、安全には使えなかったのだな。
つまり戻り値でのエラーチェック。利点としては、必ずエラーが起きた場合を想定して作るので、漏れが少ない。難点はとにかく面倒だということ。
(このあたりはここやここに奮闘の記録が残っています)
.NETの場合はフレームワーク自体がバンバン例外を発生させるので、自分の作ったメソッドだけ戻り値でエラーチェックしても、エラー処理が2パターンになって煩雑化する。
ここは、フレームワークの例外処理に沿うのが一番。
そこで、動きを確かめるために、気になるパターンをいろいろ試してみた。
その1 メソッドからメソッドを呼び出して、そこで例外が起きたという基本パターン。
class Program
{
static void Main(string[] args)
{
Program p = new Program();
try
{
p.FirstMethod();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
Console.WriteLine(ex.StackTrace);
}
Console.WriteLine(“Enterキーを押すと終了”);
Console.ReadLine();
}
private void FirstMethod()
{
SecondMethod();
}
private void SecondMethod()
{
throw new Exception(“SecondMethodでエラー”);
}
}
「SecondMethodでエラー」が表示される。
スタックトレースはSecond、そしてFirstの順で表示。
つまり深いところで起きたエラーの内容がそのまま拾えるということだ。
その2 次にFirstMethodを次のようにしてみた。
private void FirstMethod()
{
try
{
SecondMethod();
}
catch (Exception ex)
{
//なにかのエラー処理
//そのままエラーを投げてみる
throw ex;
}
}
同じく「SecondMethodでエラー」が表示。
しかし、スタックトレースはFirstのみ表示。Secondは出てこない。なぜだろう?
どこでエラーが起きたかわからなくなりそうだな。
Javaもこんな動きだったっけ?
その3 次にFirstMethodをこんな風にしてみる
private void FirstMethod()
{
try
{
SecondMethod();
}
catch (Exception ex)
{
//新たに例外を起こしてみる
throw new Exception(“だめだぜ子猫ちゃん”);
}
}
「だめだぜ子猫ちゃん」表示。
スタックトレースもFirstのみ。Secondで起きたエラーの詳細メッセージは消失。
まぁ、それはそうだろう。
その5 InnerExceptionを使ってみる。
private void FirstMethod()
{
try
{
SecondMethod();
}
catch (Exception ex)
{
//InnerExceptionを使ってみる
throw new Exception(“だめだぜ子猫ちゃん”,ex);
}
}
Mainメソッドも以下のように変更。
static void Main(string[] args)
{
Program p = new Program();
try
{
p.FirstMethod();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
Console.WriteLine(ex.StackTrace);
Console.WriteLine(“”);
Console.WriteLine(ex.InnerException.Message);
Console.WriteLine(ex.InnerException.StackTrace);
}
Console.WriteLine(“Enterキーを押すと終了”);
Console.ReadLine();
}
「だめだぜ子猫ちゃん」と、トレースにFirstMethod。
「SecondMethodでエラー」と、トレースにSecondMethod,FirstMethod。
SecondMethodで起きた詳細のエラー情報も消失することなく、FirstMethodでもエラーの情報を付加して呼び出し元に通知できる。
こうやってみると、その1かその5が一番使うパターンかもしれない。
なんらかのエラー処理を行って例外をそのまま呼び出し元に渡すという、その2は結構使うかと思ったけど、スタックトレースが一部消失するのはよろしくない。
そこで、
その6 FirstMethodで例外をキャッチして表示してみる
private void FirstMethod()
{
try
{
SecondMethod();
}
catch (Exception ex)
{
//なにかのエラー処理
Console.WriteLine(ex.Message);
Console.WriteLine(ex.StackTrace);
//そのままエラーを投げてみる
throw ex;
}
finally
{
Console.WriteLine(“FirstMethodの終了処理”);
}
}
「なにかのエラー処理」の後のex.StackTraceではSecondMethodも表示されている。
これ以下スタックトレースはここでログにはき出すので必要ない、とか言う場合はこれでもいいのかもしれない。