回答:
:私が使用したいArgumentException
、ArgumentNullException
とArgumentOutOfRangeException
。
ArgumentException
–引数に問題があります。ArgumentNullException
–引数がnullです。ArgumentOutOfRangeException
–私はこれをあまり使用しませんが、一般的な使用法は、コレクションへのインデックス付けと、非常に大きいインデックスの指定です。議論自体にそれほど焦点を当てず、むしろ全体として呼びかけを判断する他のオプションもあります:
InvalidOperationException
–引数はOKである可能性がありますが、オブジェクトの現在の状態ではありません。クレジットはSTW(以前のYoooder)に送られます。彼の答えも投票してください。NotSupportedException
–渡された引数は有効ですが、この実装ではサポートされていません。FTPクライアントを想像してみて、クライアントがサポートしていないコマンドを渡します。トリックは、メソッドをそのように呼び出すことができない理由を最もよく表す例外をスローすることです。理想的には、例外は何が問題であったのか、なぜそれが間違っているのか、そしてどのように修正するのかについて詳しく説明する必要があります。
エラーメッセージがヘルプ、ドキュメント、またはその他のリソースを示しているのが大好きです。たとえば、MicrosoftはKB記事で優れた最初のステップを実行しました。たとえば、「Internet ExplorerでWebページにアクセスすると「操作が中止されました」というエラーメッセージが表示されるのはなぜですか?。エラーが発生すると、エラーメッセージのKB記事が表示されます。彼らがうまくやっていないのは、具体的に失敗した理由を教えてくれないことです。
コメントをありがとうSTW(元Yoooder)に再び。
あなたのフォローアップに応えて、私はをスローしArgumentOutOfRangeException
ます。MSDNがこの例外について言っていることを見てください。
ArgumentOutOfRangeException
メソッドが呼び出され、メソッドに渡された引数の少なくとも1つがnull参照(Nothing
Visual Basicの場合)ではなく、有効な値が含まれていない場合にスローされます。
したがって、この場合は値を渡していますが、範囲が1〜12であるため、それは有効な値ではありません。ただし、それを文書化する方法により、APIが何をスローするかが明確になります。私が言うかもしれないArgumentOutOfRangeException
が別の開発者が言うかもしれないのでArgumentException
。簡単にし、動作を文書化します。
FormatException
:引数の形式が無効である場合、または複合形式文字列の形式が正しくない場合にスローされる例外。
ジョシュの回答に投票しましたが、リストにもう1つ追加したいと思います。
引数は有効ですが、オブジェクトが引数を使用してはならない状態の場合、System.InvalidOperationExceptionがスローされます。
MSDNから取得した更新:
InvalidOperationExceptionは、メソッドの呼び出しの失敗が無効な引数以外の理由で発生した場合に使用されます。
オブジェクトにPerformAction(enmSomeAction action)メソッドがあり、有効なenmSomeActionsがOpenおよびCloseであるとします。連続して2回PerformAction(enmSomeAction.Open)を呼び出すと、2番目の呼び出しでInvalidOperationExceptionがスローされます(arugmentは有効でしたが、コントロールの現在の状態ではないため)。
防御的にプログラミングすることですでに正しいことをしているので、もう1つ例外があります。ObjectDisposedExceptionです。 場合は、あなたのオブジェクトは、IDisposableを実装し、その後、あなたは常に配置された状態を追跡するクラス変数を持っている必要があります。オブジェクトが破棄され、そのメソッドが呼び出された場合は、ObjectDisposedExceptionを発生させる必要があります。
public void SomeMethod()
{
If (m_Disposed) {
throw new ObjectDisposedException("Object has been disposed")
}
// ... Normal execution code
}
更新:フォローアップに答えるには:これは少しあいまいな状況であり、特定のデータセットを表すために使用されるジェネリック(.NETジェネリックの意味ではない)データ型によって、もう少し複雑になります。列挙型またはその他の強く型付けされたオブジェクトの方が理想的ですが、常に制御できるとは限りません。
個人的にはArgumentOutOfRangeExceptionに頼り、有効な値が1〜12であることを示すメッセージを提供します。私の推論は、月について話すとき、月のすべての整数表現が有効であると仮定すると、1〜12の範囲の値を期待しているということです。特定の月(31日の月など)のみが有効である場合、Range自体を処理せず、有効な値を示す一般的なArgumentExceptionをスローし、メソッドのコメントにそれらを文書化します。
実際の値と最適な例外に応じて:
ArgumentException
(値に問題があります)
ArgumentNullException
(これは許可されていませんが、引数はnullです)
ArgumentOutOfRangeException
(引数の値が有効範囲外です)
これが十分に正確でない場合は、独自の例外クラスをから派生させてくださいArgumentException
。
Yoooderの答えは私を啓発しました。入力はいつでも無効である場合は無効ですが、システムの現在の状態で有効でない場合は予期しない入力です。したがって、後者の場合InvalidOperationException
はが妥当な選択です。
ArgumentExceptionは、メソッドが呼び出され、渡された引数の少なくとも1つが、呼び出されたメソッドのパラメーター仕様を満たしていない場合にスローされます。ArgumentExceptionのすべてのインスタンスは、無効な引数と、引数の予期される値の範囲を説明する意味のあるエラーメッセージを運ぶ必要があります。
特定のタイプの無効性のために、いくつかのサブクラスも存在します。リンクには、サブタイプの概要とそれらがいつ適用されるかが示されています。
短い答え:
どちらでもない
より長い答え:
Argument * Exception(コンポーネントライブラリなどの製品であるライブラリを除く)の使用は臭いです。例外は例外的な状況を処理することであり、バグではなく、ユーザー(つまりAPIコンシューマー)の不足ではありません。
最長の回答:
ライブラリを作成しない限り、無効な引数に対して例外をスローするのは失礼です。
私は2つ(またはそれ以上)の理由でアサーションの使用を好みます:
null例外の処理は次のようになります(皮肉なことです)。
try {
library.Method(null);
}
catch (ArgumentNullException e) {
// retry with real argument this time
library.Method(realArgument);
}
例外は、状況が予想されるが例外的な場合(IO障害など、消費者の制御の及ばない事態が発生した場合)に使用されます。Argument * Exceptionはバグを示しており、(私の意見では)テストで処理され、Debug.Assertで支援されます
ところで、この特定のケースでは、intの代わりにMonthタイプを使用できます。C#はタイプセーフティ(Aspect#rulez!)に関しては不十分ですが、これらのバグをすべて一緒に防止(またはコンパイル時にキャッチ)することができます。
そして、はい、MicroSoftはそれについて間違っています。
使用できる標準のArgumentExceptionがあります。または、サブクラスを作成して独自に作成することもできます。いくつかの特定のArgumentExceptionクラスがあります。
http://msdn.microsoft.com/en-us/library/system.argumentexception(VS.71).aspx
どちらが最もよく機能します。