ユーザーがプログラムによってエラー条件を識別できるようにする場合は、独自のユーザー定義例外を作成できます。
.NET Framework には、Exception 基本クラスから最終的に派生した例外クラスの階層があります。
実際にException派生クラスを作ってみる
ユーザー定義例外のクラス名の終わりに “Exception” という単語を付けておくと、例外クラスであることが分かりやすくなります。
例として、CanNotDoAnythingExceptionという例外クラスを作ってみます。
public class CanNotDoAnythingException : Exception
Exceptionクラスの派生クラスですので’ : Exception’がつきます。
ExceptionクラスはSystem名前空間のクラスです(System.Exception)ので
using System;
は必要です。
推奨される 3 つの共通コンストラクター
Exception派生クラスでは、下記のようなコンストラクターを3つ用意しておくと他の例外クラスと同じように扱うことができます。
- 引数なしのコンストラクタ
- メッセージ文字列のみを引数とするコンストラクタ
- メッセージ文字列と発生済み例外オブジェクトを渡すコンストラクタ
これら3つのコンストラクタは基底となるExceptionクラスに用意されているコンストラクタです。
引数なしのコンストラクタ
実装です。
/// <summary> /// コンストラクタ /// </summary> public CanNotDoAnythingException() { // }
このコンストラクタでオブジェクトを生成した時のMessageプロパティは
「”種類 ‘ExceptionTest.CanNotDoAnythingException’ の例外がスローされました。”」
になります。
引数なしでのMessageプロパティの文字列を変更するには
/// <summary> /// コンストラクタ /// </summary> public CanNotDoAnythingException() : base("<ここにメッセージを書く>") { // }
とします。
Messageプロパティは、派生クラス内部でも設定はできない(読み取り専用でgetのみしかありません)ので注意してください。
メッセージ文字列のみを引数とするコンストラクタ
仮引数’message’の文字列がMessageプロパティの文字列としてセットされます。
/// <summary> /// メッセージ文字列を渡すコンストラクタ /// </summary> /// <param name="message">メッセージ文字列</param> public CanNotDoAnythingException(string message) : base(message) { // }
一番使う機会が多いコンストラクタです。
メッセージ文字列と発生済み例外オブジェクトを渡すコンストラクタ
実装はこのようになります。
/// <summary> /// メッセージ文字列と発生済み例外オブジェクトを渡すコンストラクタ /// </summary> /// <param name="message">メッセージ文字列</param> /// <param name="innerException">発生済み例外オブジェクト</param> public CanNotDoAnythingException(string message, Exception innerException) : base(message, innerException) { // }
このコンストラクタは、あまりなじみがないかもしれません。
下記の例のように、例外を「入れ子」で発生させるときに使います。
class Program { static void Func() { throw new CanNotDoAnythingException("なにもしないの?"); } static void Main(string[] args) { try { try { Func(); } catch (Exception e) { throw new CanNotDoAnythingException("なにもしないって!", e); } } catch (Exception e) { string msg = e.InnerException.Message + " " + e.Message; System.Diagnostics.Debug.WriteLine(msg); Console.WriteLine(msg); } } }
23行目での変数’msg’に格納されたメッセージは、
“なにもしないの? なにもしないって!”
と、2つの例外オブジェクトの情報を扱うことができるようになります。
今回作成した例外クラスのソース
public class CanNotDoAnythingException : Exception { /// <summary> /// コンストラクタ /// </summary> public CanNotDoAnythingException() : base("なにもしない") { // 普通のコンストラクタ } /// <summary> /// メッセージ文字列を渡すコンストラクタ /// </summary> /// <param name="message">メッセージ文字列</param> public CanNotDoAnythingException(string message) : base(message) { // メッセージ文字列を渡すコンストラクタ } /// <summary> /// メッセージ文字列と発生済み例外オブジェクトを渡すコンストラクタ /// </summary> /// <param name="message">メッセージ文字列</param> /// <param name="innerException">発生済み例外オブジェクト</param> public CanNotDoAnythingException(string message, Exception innerException) : base(message, innerException) { // メッセージ文字列と発生済み例外オブジェクトを渡すコンストラクタ } }