例外を区別して扱う
例外には多くの種類があり、ファイルが見つからないというのは、そのうちの一種類でしかない。StreamReaderクラスのコンストラクタは、何種類かの例外を発生させる可能性がある。例えば、ディレクトリが見つからない、という例外を発生させる可能性もある。上記のサンプル・ソースに、存在しないディレクトリの指定を書き加えたら、いったい何が起こるだろうか。
1: using System;
2: using System.IO;
3: using System.Text;
4:
5: namespace ConsoleApplication36
6: {
7: class Class1
8: {
9: static void Main(string[] args)
10: {
11: try
12: {
13: StreamReader reader = new StreamReader("存在しないディレクトリ\\存在しない.txt",Encoding.GetEncoding("Shift_JIS"));
14: Console.Write( reader.ReadToEnd() );
15: reader.Close();
16: }
17: catch( FileNotFoundException e )
18: {
19: Console.WriteLine("ファイル" + e.FileName + "が見つかりません。");
20: }
21: }
22: }
23: } |
|
例外を発生させるサンプル・プログラム5 |
オープンしようとするファイルのファイル名に、存在しないディレクトリ名を付けている。 |
これを実行すると以下のようになる。
|
サンプル・プログラム5の実行結果 |
catch文で指定していないDirectoryNotFoundExceptionクラスの例外が発生している。
|
見てのとおり、FileNotFoundExceptionクラスをキャッチするコードは何の働きも示さず、最初のサンプル・ソースのように、システムが例外の結果をコンソールに出力してしまった。画面写真を見て分かるとおり、ここで起きた例外は、FileNotFoundExceptionクラスではなく、DirectoryNotFoundExceptionクラスである。いかにtry文を書こうと、catch文で指定しなかった例外に関しては、何の機能も発揮していないことが分かるだろう。
では、どうすれば、FileNotFoundExceptionクラスも、DirectoryNotFoundExceptionクラスも、どちらも自分でエラー処理を行えるのだろうか? 答は以下のとおりだ。
1: using System;
2: using System.IO;
3: using System.Text;
4:
5: namespace ConsoleApplication37
6: {
7: class Class1
8: {
9: static void Main(string[] args)
10: {
11: try
12: {
13: StreamReader reader = new StreamReader("存在しないディレクトリ\\存在しない.txt",Encoding.GetEncoding("Shift_JIS"));
14: Console.Write( reader.ReadToEnd() );
15: reader.Close();
16: }
17: catch( FileNotFoundException e )
18: {
19: Console.WriteLine("ファイル" + e.FileName + "が見つかりません。");
20: }
21: catch( DirectoryNotFoundException e )
22: {
23: Console.WriteLine("ディレクトリが見つかりません。");
24: }
25: }
26: }
27: } |
|
2種類の例外を処理するサンプル・プログラム6 |
1つのtry文に対して、2つのcatch文を記述している |
これを実行すると以下のようになる。
|
サンプル・プログラム6の実行結果 |
ディレクトリが見つからないという例外もキャッチされ、適切なエラー・メッセージが表示されている。
|
このように、1個のtry文に対応するcatch文は1つでなければならないということはない。キャッチしたい例外の数だけ、catch文を並べて書いてよい。
すべての例外をキャッチする方法
何種類もある例外をすべてキャッチしようとすると、ソースに書くべきコードも増える。しかし、トラブルがあったことだけ分かればよく、トラブルの種類ごとに処理を分けなくてもかまわない、という状況なら話を簡単にすることができる。以下は、1個のcatch文であらゆる例外をキャッチさせている例である。
1: using System;
2: using System.IO;
3: using System.Text;
4:
5: namespace ConsoleApplication38
6: {
7: class Class1
8: {
9: static void Main(string[] args)
10: {
11: try
12: {
13: StreamReader reader = new StreamReader("存在しないディレクトリ\\存在しない.txt",Encoding.GetEncoding("Shift_JIS"));
14: Console.Write( reader.ReadToEnd() );
15: reader.Close();
16: }
17: catch( Exception e )
18: {
19: Console.WriteLine(e.GetType().FullName + "の例外が発生しました。");
20: }
21: }
22: }
23: } |
|
catch文を1つにしたサンプル・プログラム7 |
例外の種類に関係なく、すべての例外を1つのcatch文でキャッチする。 |
これを実行すると以下のようになる。
|
サンプル・プログラム7の実行結果 |
catchブロック内では発生した例外からそのクラスを取得し、クラス名をフルネームで表示している。
|
変更したのは17行目である。例外のクラス名として“Exception”を指定した。例外で使用するクラスは、すべてExceptionクラスを継承したものである。すべての例外クラスの継承元であるExceptionクラスを指定するということは、すべての例外状況にマッチするということである。つまり、実際に起きた例外がDirectoryNotFoundExceptionクラスであっても、これはExceptionクラスから派生したクラスなので、Exceptionクラスの機能をすべて含んでおり、Exceptionクラスとして扱うこともできる。そのため、Exceptionクラスをキャッチするcatch文で、DirectoryNotFoundExceptionクラスもキャッチされるようになる。
この結果、try文の中で発生するあらゆる例外は、この17行目のcatch文でキャッチされるのである。
Insider.NET 記事ランキング
本日
月間