例外クラス

 前節で見たように、.NET Frameworkで用意されているメソッドで発生する可能性があるものは、MSDNライブラリーに説明が載せられているので、その例外クラス名を使用して例外処理を記述できます。例外処理はそれ以外にも、自分で例外クラスを作って、発生(スロー)させることもできます。

 例外クラスを作成するには次のように記述します。

例外クラス定義の書式
class 例外クラス名
 : Exception
{
 …
}

 自分で作った例外クラスは自分でスローしなくてはなりません。例外をスローするには次のように記述します。

例外クラススローの書式
throw 例外オブジェクト;

 ここで、先回作成したBusクラスを修正しましょう。今までは、乗車や降車をするときに走っていないかどうかなどを調べ、異常がある場合はその旨のメッセージを返すように作ってきました。それを例外処理に書き換えましょう。

○ プロジェクト

 プロジェクトを作成して確認してみましょう。

プロジェクトの種類 コンソール アプリケーション
プロジェクト名 ThrowTest

サンプルダウンロード

○ 作成の準備

 「InheritanceTest」プロジェクトを修正して作成しましょう。InheritanceTestフォルダーをコピーして、作成するプロジェクト名にフォルダー名を変更してください。

○ プログラム

 例外を表すクラスを作成しましょう。Exceptionクラスを継承した次のようなクラスを作成してください。

WarningException.cs

  1. class WarningException
  2.  : Exception
  3. {
  4.  public WarningException(string error)
  5.   : base(error)
  6.  {
  7.  }
  8. }

○ 解説

 10行目でスーパークラスにExceptionクラスを指定しています。それにより今回作成したWarningExceptionクラスはスローしてキャッチすることができるようになります。例外を表すクラスは多くの場合~Exceptionのように名前を付けます。

 12~15行目ではコンストラクタを定義しています。このコンストラクタはインスタンス生成時にスーパークラスであるExceptionクラスのコンストラクタを呼び出しています。引数として受け取ったエラーメッセージをさらに引数として渡しています。これによりMessageプロパティで引数で指定したエラーメッセージが参照できるようになります。

○ プログラム

 次にBusクラスを変更しましょう。次のように修正してください。

Bus.cs

  1. class Bus
  2.  : Car
  3. {
  4.  //プロパティ==========
  5.  public int SalesAmount { get; private set; }   //運賃
  6.  public int PassengerNumber { get; private set; }   //乗客人数
  7.  //コンストラクタ==========
  8.  public Bus()
  9.   : this(100)
  10.  {
  11.  }
  12.  public Bus(double gas)
  13.   : base(gas)
  14.  {
  15.   this.SalesAmount = 0;
  16.   this.PassengerNumber = 0;
  17.   }
  18.  //メソッド==========
  19.  //乗車させるメソッド
  20.  public void RideToBus(int fare)
  21.  {
  22.   //走行中かどうか
  23.   if (this.Speed != 0)
  24.   {
  25.    throw new WarningException("停車してください。");
  26.   }
  27.   //満席かどうか
  28.   if (this.PassengerNumber >= 50)
  29.   {
  30.    throw new WarningException("満席のため、乗車できません。");
  31.   }
  32.   //料金と、乗車人数を加算
  33.   this.SalesAmount += fare;
  34.   this.PassengerNumber++;
  35.  }
  36.  //降車させるメソッド
  37.  public void GetOffBus()
  38.  {
  39.   //走行中かどうか
  40.   if (this.Speed != 0)
  41.   {
  42.    throw new WarningException("停車してください。");
  43.   }
  44.   //乗客がいるかどうか
  45.   if (this.PassengerNumber == 0)
  46.   {
  47.    throw new WarningException("乗客はいません。");
  48.   }
  49.   //乗車人数を減算
  50.   this.PassengerNumber--;
  51.  }
  52. }

○ 解説

 31、49行目では、処理の中でエラーが発生した場合は文字列を返す仕組みから例外をスローする仕組みに変更するため、戻すデータがなくなりました。そのため、戻り値の型をstringからvoidに変更しています。

 36、41、54、59行目では、エラーが発生した場合にその時のエラーメッセージをreturn文で返していましたが、throw文を使って例外をスローさせるように変更しました。

○ プログラム

 次にMainメソッドを変更しましょう。次のように修正してください。

Program.cs

  1. static void Main(string[] args)
  2. {
  3.  //インスタンスを生成する
  4.  Bus bus = new Bus(150);
  5.  //現在の状態を表示する
  6.  ShowData(bus);
  7.  while (true)
  8.  {
  9.   try
  10.   {
  11.    //操作を入力
  12.    Console.Write("1)加速 2)減速 3)給油 7)乗車 8)降車 9)終了:");
  13.    string inputdata = Console.ReadLine();
  14.    //操作によって分岐する
  15.    switch (inputdata)
  16.    {
  17.     case "1":
  18.      //加速する
  19.      bus.SpeedUp(5);
  20.      ShowData(bus);
  21.      break;
  22.     case "2":
  23.      //減速する
  24.      bus.SpeedDown(5);
  25.      ShowData(bus);
  26.      break;
  27.     case "3":
  28.      //給油する
  29.      bus.Gas = 80;
  30.      ShowData(bus);
  31.      break;
  32.     case "7":
  33.      //乗車する
  34.      bus.RideToBus(200);
  35.      ShowData(bus);
  36.      break;
  37.     case "8":
  38.      //降車する
  39.      bus.GetOffBus();
  40.      ShowData(bus);
  41.      break;
  42.     case "9":
  43.      //プログラムを終了する
  44.      return;
  45.    }
  46.   }
  47.   catch (WarningException e)
  48.   {
  49.    Console.WriteLine(e.Message);
  50.   }
  51.   catch (Exception e)
  52.   {
  53.    Console.WriteLine("エラーが発生しました。");
  54.    Console.WriteLine(e.Message);
  55.   }
  56.  }
  57. }

○ 解説

 30~77行目では、try~catch文が記述されています。56、61行目で、バスオブジェクトのメソッドが呼び出されると、状態によって例外(WarningException)がスローされてきます。その場合は、69行目でキャッチされ、71行目の処理が行われます。73行目はWarningException以外がtry文の中でスローされたときにキャッチされます。

 catch文は複数指定することができます。try文でスローされた例外オブジェクトに応じてキャッチされます。それぞれのcatch文が上から順に評価されていきます。そのため、Exception型のcatchは最後に指定しないとエラーとなります。上の方にExeption型の指定をすると必ずそこでキャッチされ、下に指定したcatch文は使われないからです。

前へ   次へ