連載

C#入門

第18回 例外とエラー処理

(株)ピーデー
川俣 晶
2001/12/22


例外を区別して扱う

 例外には多くの種類があり、ファイルが見つからないというのは、そのうちの一種類でしかない。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文でキャッチされるのである。


 INDEX
  第18回 例外とエラー処理
    1.例外とは何か?
  2.例外を区別して扱う
    3.確実な終了処理を行うfinally
    4.深い階層からの例外
    5.例外処理の再発生
    6.例外クラスのインスタンスを活用する
 
「C#入門」


Insider.NET フォーラム 新着記事
  • 第2回 簡潔なコーディングのために (2017/7/26)
     ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている
  • 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
     Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう
  • 第1回 明瞭なコーディングのために (2017/7/19)
     C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える
  • Presentation Translator (2017/7/18)
     Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

Insider.NET 記事ランキング

本日 月間