C# – カスタム例外を作成する方法

カスタム例外を作成するには、次のように Exception クラスのサブクラスを作成します:

public class SimpleCustomException : Exception
{
	public SimpleCustomException(string message) : base(message) { }
	public SimpleCustomException() { }
}
Code language: C# (cs)

次に、次のように、他の例外と同じようにスローします。

throw new SimpleCustomException("Cannot call this method on days that end with 'y'")
Code language: C# (cs)

基本コンストラクターにカスタム エラー メッセージを渡すことをお勧めします。この例外が処理されない場合、または例外をログに記録している場合は、次のように例外名とメッセージが表示されます:

SimpleCustomException: Cannot call this method on days that end with 'y'Code language: plaintext (plaintext)

例 – 無効なデータが渡されたときにカスタム例外をスローする

独自のカスタム例外を作成すると、非常に具体的な例外を作成できます。非常に具体的な例外をスローしてキャッチすることは、クリーンなエラー処理の一部です。

次の例は、無効なデータが渡されたときにカスタム例外をスローするバイナリ文字列パーサー クラスを示しています。これは、問題の内容と期待されるデータを正確に説明する非常に具体的な例外をスローします。

1 – カスタム例外クラスを追加

このカスタム例外は、無効な binaryString を取得し、予想される形式を説明するエラー メッセージに入れ、有効な入力の例を示しています。

public class InvalidBinaryStringException : Exception
{
	public InvalidBinaryStringException(string binaryString)
		: base($"Bad binary string: {binaryString}. Binary string must be 0's and 1's and the length must be a multiple of 8. Example: 00000001.")
	{
	}
}
Code language: C# (cs)

2 – エラー条件が検出されたときに例外をスローする

BinaryStringUtil クラスは、バイナリ文字列を解析する前に、渡された binaryString をチェックし、入力が無効な場合はカスタムの InvalidBinaryStringException をスローします。

public class BinaryStringUtil
{
	public static byte[] Parse(string binaryString)
	{
		if (binaryString.Length % 8 != 0 || Regex.IsMatch(binaryString, "[^01]"))
		{
			throw new InvalidBinaryStringException(binaryString);
		}

		//Parse binaryString into byte[]
		
		return new byte[] { };

	}
}
Code language: C# (cs)

なぜ代わりに ArgumentException または FormatException をスローしないのかと疑問に思うかもしれません。確かに、これらの例外をスローして、同じエラー メッセージを渡すことができます。ただし、カスタム例外を使用する次の理由を考慮してください:

  • エラー メッセージをカプセル化します。上記のコードが単純に binaryString を例外に渡していることに注意してください。
  • たとえば、ログ監視ツール (Splunk など) を使用していて、この特定のエラーが発生したときにアラート メールを送信したいとします。ログで「InvalidBinaryStringException」を探すだけです。 ArgumentException を使用していた場合は、代わりにエラー メッセージ (「Bad binary string...」) を探す必要があります。
  • クライアント コードは、InvalidBinaryStringException をキャッチして適切に処理できます。解析コードにバグがあり、呼び出しているメソッドが ArgumentException をスローしているとします。クライアントがこの非固有の例外をキャッチしていた場合、クライアント コードは間違ったエラー処理動作を行い、バグは隠されます。

3 – 単体テストを追加して、コードが例外をスローすることを証明する

次のパラメーター化された単体テストでは、バイナリ文字列が有効な長さではない場合と、無効な文字が含まれている場合の 2 つのエラー条件をテストします。 ExpectedException 属性の代わりに Assert.ThrowsException を使用していることに注意してください。

[DataRow("01")]
[DataRow("0100000a")]
[TestMethod()]
public void ParseTest_WhenBadBinaryString_ThrowsException(string binaryString)
{
   Assert.ThrowsException<InvalidBinaryStringException>(() => BinaryStringUtil.Parse(binaryString));
}

Code language: C# (cs)