Exceptionクラスを生成しない例外はthrowできる?
例外を投げるには”throw”キーワードを用いますが、try節の中で引数なしでthrowを実装できなくなっています
(「引数なしの throw ステートメントは catch 句以外では使えません。」と言われます)。
仮に下記のようなコードを実行するとどうなるでしょう
try { throw null; } catch (Exception ex) { Console.WriteLine("[1] Catch exception with exception object " + ex.Message); } catch { Console.WriteLine("[2] Catch exception"); }
当然、例外は発生します。この場合の例外は[1]の”catch (Exception ex)”節のほうで捕捉されます。
見れば納得するのですが、「System.NullReferenceException」が発生します。
Exceptionクラスで例外を投げる
一番簡単なExceptionクラスを使った例外の実装は
try { throw new Exception(); } catch (Exception ex) { Console.WriteLine(ex.Message); }
ですが、この場合、catchしたほうで、「Messageプロパティは空になるのか?」と思われそうですが、実はMessageプロパティには「種類 ‘System.Exception’ の例外がスローされました。」というメッセージが入ります。
ただ、「種類 ‘System.Exception’ の例外がスローされました。」ではさっぱり分からないので、やはりExceptionクラスを通じて「どういった例外が発生したのか」が分かるようにしておいたほうが良いです。
(種別に応じたたくさんのException派生クラスがあるのですが、今回はExceptionクラスで)
Exceptionクラスのコンストラクタはオーバーロードされていて、引数には「発生した例外に関するメッセージの文字列」と「今回生成する前に発生していた例外オブジェクト」を渡すことができます。
普段は「発生した例外に関するメッセージの文字列」だけをつけてExceptionクラスを生成することのほうが多いです。
try { throw new Exception("An exception occurs."); } catch (Exception ex) { Console.WriteLine(ex.Message); }
こうすると、catchしたには、Messageプロパティに「An exception occurs.」というメッセージが格納されています。
どこから投げた例外?
下記のようなメソッド(関数)があったとします。
static void func1() { throw new NotImplementedException("Not Implemented!!"); } static void func2() { throw new NotImplementedException("Not Implemented!!"); } static void func3() { throw new NotImplementedException("Not Implemented!!"); } static void switchfunc(int i) { switch (i) { case 1: func1(); break; case 2: func2(); break; case 3: func3(); break; default: break; } }
switchfunc()をコールして変数’i’で呼ばれるメソッドが切り替わりますが、呼び出されたメソッドからはNotImplementedException(メソッドまたは操作が実装されない場合にスローされる例外)が発生するのですが、Messageプロパティもすべて同じメッセージ(“Not Implemented!!”)しか実装されていません。
Messageプロパティの実装にメソッド名を入れるという方法もあるかもしれません(メソッド名を入れる前にメソッドの実装しましょう(^^;)が、Exceptionクラスには便利なプロパティがあり、例外が発生したメソッドを持つプロパティがあります。
TargetSiteというプロパティに例外を投げたメソッド名が分かります(なぜか先頭が大文字なんですけど・・・)。