カスタム例外を作成するには、次のように 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)