例外 -自分の例外-

ホームC#プログラミング応用講義 > 自分の例外

目次

例外クラスの定義

前単元の基礎的な例外処理を、さまざまな種類に対応させることでほとんどの場合は事足ります。
しかし、C# における例外はオブジェクト指向をフル利用することにより、自分で例外クラスを作り、そして例外を投げることができます。

例外を自分で作ることは非常に簡単ですが、ほとんどの場合は .NET に用意された数々の例外クラスで事足りるため、ここではあまり詳しくしません。
例外の4つのキーワードのうち2つ(throw / finally)を説明するために、自分で例外を作ってみます。

ここでは前回の10を割るプログラムの中で、結果が整数にならない場合に例外を発生させたいと思います。
その例外クラスの名前を「IntException」としましょう。

.NET エンジンが例外と認める例外は SystemException から派生しますが、自分で作る例外は ApplicationException から派生します。
class IntException : ApplicationException
実は例外クラスはほとんどこの ApplicationException にさまざまなメンバが用意されているので、クラスの中身がなくてもクラスが存在すれば、すなわち { と } の中に何も書かなくてもこれだけで例外クラスとして立派に働きますが、それでは面白くないので ToString() メソッドをオーバーライドしましょう。
(派生・オーバーライドなどに関しては後にやります)
public override string ToString()
{
return Message;
}
このメソッドは利用しませんが、通常 Message を返すこのメソッドはオーバーライドするのが普通なので一応しておきます。(また言いますが、この部分はなくても、 ApplicationException クラスの派生クラスである IntException があれば例外クラスとして利用できます)

よって、上の IntException クラスは以下のようになります。
class IntException : ApplicationException
{
public override string ToString()
{
return Message;
}
}

実装と利用

自分で作った例外はシステムによって自動的に呼び出される例外とは違い、自分で起こす必要があります。例外を自分か ら起こすことを「投げる」という意味で例外を「スローする」といいます。

例外をスローするには前に述べたキーワード throw を使います。throw の後には例外オブジェクトを続けます。
thorw new コンストラクタ();

ここでは IntException クラスですので
throw new IntException();
となります。

ちなみに IntException クラスで ApplicationException クラスのコンストラクタを base() を利用して継承することも可能ですが、宣言していないためデフォルトコンストラクタを呼び出すことになります。

また、例外をスローするタイミングは「10を割っても整数にならない値」がコマンドライン引数として指定されたときです。例えば2や4,6はこの例外に値 します。
結局例外が発生しないのは10の約数である1,2,5,10だけです。

割り切れるかどうかは、余りで調べることができます。剰余は「%」演算子を利用して求めることができます。
int x = 10 % 3;  // x = 1 です
つまり、例外が発生するのは剰余が 0 でないときです。

これですべての情報がそろいました。ソースを書いてみましょう。
using System;

class IntException : ApplicationException
{
public override string ToString()
{
return Message;
}
}

class Test
{
public static void Main(string[] args)
{
try
{
int i = int.Parse(args[0]);
const int a = 10;
if (a%i != 0)
throw new IntException();

Console.WriteLine(a/i);
}

catch(DivideByZeroException)
{
Console.WriteLine("0を入力するバカがあるか!!");
}
catch(IndexOutOfRangeException)
{
Console.WriteLine("コマンドライン引数を入力して実行せんかい!!");
}
catch(IntException)
{
Console.WriteLine("1,2,5 のどれかを入力すると整数になると思うよ~");
}
}
}
catch の最後が自分で作った例外です。まるで他のシステム例外と同じように利用することができるということがお分かりと思います。


さて、あと1つ使っていないキーワードがあります。finally です。
しかし、ここでは特に明記して破棄すべきオブジェクトもないので、終了することをユーザに伝えましょう。

この終わった合図はいつ何時も実行される必要があります。例外が起きても起きなくても実行し なければなりません。
そのような必要があるときだけ finally が役に立ちます。

では、上のプログラムに finally を付け加えて例外学習の終了プログラムとしましょう。
using System;

class IntException : ApplicationException
{
public override string ToString()
{
return Message;
}
}

class Test
{
public static void Main(string[] args)
{
try
{
int i = int.Parse(args[0]);
const int a = 10;
if (a%i != 0)
throw new IntException();

Console.WriteLine(a/i);
}

catch(DivideByZeroException)
{
Console.WriteLine("0を入力するバカがあるか!!");
}
catch(IndexOutOfRangeException)
{
Console.WriteLine("コマンドライン引数を入力して実行せんかい!!");
}
catch(IntException)
{
Console.WriteLine("1,2,5 のどれかを入力すると整数になると思うよ~");
}

finally
{
Console.WriteLine("終了します.....");
}
}
}

[ ステップアップC# ] [ C#プログラミング応用講義 ]