2012-02-09 16 views
2

.NET Frameworkには多くの事前定義された例外があります。たとえば、無効なパラメータが私のメソッドに渡された場合、ArgumentException(または、パラメータがnullだった場合)を発生させるはずです。現在のオブジェクト状態に対して無効なメソッドが呼び出された場合、私はInvalidOperationExceptionを呼び出すことになっています。あらかじめ定義されたThisIsABugExceptionはありますか?

"このコードは決してに届くはずがありません"の場合、あらかじめ定義された例外はありますか?私は正当化される、そのような稀な場合のために私自身の例外を作成するとは思わない

void myMethod() { 
    int a; 

    ... /* Some complex code that manipulates a. In the end, "a" can only be 1 or 2. */ 

    switch (a) { 
     case 1: ... 
     case 2: ... 
     default: // just an extra sanity check 
      // Oops, we should never be here. 
      // There's apparently some bug in the code above. 
      throw new ThereIsABugInTheCodeException(); 
    } 
} 

:ここでは例です。一方、投げているのはExceptionis discouraged as wellです。私はAssertionFailedExceptionのいくつかの種類が適切だろうと思うが、私は.netフレームワークで何も見つかりませんでした。 (つまり、どちらのオプションではありませんのでTrace.Assertは、例外をスローしないことに注意してください。)


EDITを:明確にする:aは引数ではありません。メソッドの途中で、私は正気チェックを行います(メソッドの最初のコードが正しい場合は、必ずしも必要ではありません)。私は健全性チェックが失敗し、例外をスローしたいと思います。どちらを投げますか? ArgumentException should only be thrown if the caller of the method did something wrongのため、ArgumentExceptionは正解とは思われません。それはここでは当てはまりません。 メソッド自体は、実行時にバグを含んでいることを認識します。

答えて

4

奇妙なことに、.NET Frameworkには、論理エラーまたは内部エラーを記述するための例外はありません。一方、.NET Frameworkは、内部エラーの例外をスローする必要がないような品質レベルを持つ必要があります。 .NET API呼び出しを信用しますか?ドキュメントにはInternalErrorExceptionがスローされる可能性があることが記載されていますか? SystemExceptionから派生した例外はフレームワークで使用される例外であることに注意してください。これらの例外を再利用すると便利ですが、フレームワーク/アプリケーションではなく、フレームワークで使用するために例外が作成されました。

あなたはあなたの方法が予期しない方法で呼ばれる場合にArgumentExceptionArgumentNullExceptionArgumentOufOfRangeExceptionNotSupportedExceptionInvalidOperationExceptionを使用することができます。

独自のInternalErrorExceptionを作成することもできます。

マイクロソフトでは、この問題の一般的な解決方法はCode Contractsです。コンパイル時に多くの契約をチェックして、より良いコードを作成することができます。Contract.AssumeContract.Assertを使用して、コードの状態を確認できます。リライタは、条件がfalseの場合にContractExceptionをスローするコードを挿入します。この例外は、(DevLabs Code Contracts documentationから)特別な方法で細工されました:

ContractException型がパブリックタイプではなく、実行時の契約のチェックが有効になっている各アセンブリ内にネストされたプライベート型として放出されます。したがって、ContractExceptionだけを捕捉するcatchハンドラを書くことはできません。したがって、契約例外は、一般的な例外バックストップの一部としてのみ処理することができます。この設計の論理的根拠は、プログラムがArgumentNullExceptionや同様の検証例外をキャッチしないように、プログラムが契約の失敗に依存する制御ロジックを含むべきではないということです。

2

この場合、ArgumentExceptionを使用します。

a引数に予期しない値があります。

throw new ArgumentException(string.Format("Unexpected value {0} for a.", a); 

@のtodda.speot.isがコメントしたように、正確なシナリオに応じて、ArgumentOutOfRangeExceptionは、より適切であり得るけれども。

+2

私は['ArgumentOutOfRangeException'](http://msdn.microsoft.com/en-us/library/system.argumentoutofrangeexception.aspx)が必要だと思います。 –

+0

しかし、 'a'は私のメソッドの引数ではありません。これはローカル変数です!私はそれを強調するために私の質問の例を更新しました。 – Heinzi

+0

@Heinzi - これは 'switch'引数に引き渡された値です。 – Oded

3

私が表示する場合は、ArgumentException、おそらくはArgumentOutOfRangeExceptionとすることもできます。

switchはメソッドの引数にはなっていますが、十分には見えませんでしたが、明らかにそうではありません。したがって、ArgumentExceptionはおそらく適用されません。私の答えの残りはそのままです。

しかし、プログラム状態がまったく予期しない場合があります。そのような場合、私は例外(それを捕まえることができます)を使用しません。このような場合、セキュリティとデータの完全性が危機に瀕していると主張することができるので、唯一の賢明なことは、アプリケーションをできるだけ早く終了させて​​状態をさらに破壊する可能性を最小限に抑えることです。

この場合、Debug.AssertまたはTrace.Assertを使用するか、基本的にEnvironment.FailFastを呼び出す独自のハンドラをロールすることを考えてください。

アプリケーションでこのような動作が正しいかどうかは、決定する必要があります。

更新Code Contractsを調べることもできます。どのAFAIKを実行時の動作に合わせて、例外をスローするか、プロセスを中止するか、何もしないことができます。

+0

Debug.AssertとTrace.Assertの両方がメッセージボックスを表示し、コードの実行を続行します。 – Heinzi

+0

はい(デフォルト)です。あなたは[変更](http://stackoverflow.com/q/2340890/21567)その動作。個人的には、開発時にはAssert、実動コードではFailFastなどを使用します。 –

+0

この場合FailFastはあまりにも厳しいです。これをUIレイヤーにバブルさせたいので、適切な例外を探していました。 – Heinzi

0

"バグの例外"の概念はありますか?

例では、aが引数の場合は、間違いなくArgumentOutOfRangeException例外です。

あなたのコードが、私はよりも関連性のものだと思い、はこれまでを実行することが想定されていないことをいくつかのコードを実行しようとすると、「ここにねえ!バグ!上流をスローする必要があります。

+0

それはまさにそれです:コード*は決して実行されることはない*。この場合、私は何を投げますか? – Heinzi

0

ThisIsABugExceptionは概念的に間違っています。

メソッドの契約が渡された場合(パラメータが正しいため、ArgumentExceptionsがないため)、メソッドは技術的に失敗しません。なぜすべてのパラメータが正しいのか、メソッド自体のロジックが正しいのでしょうか?

したがって、メソッド契約(パラメータ)をチェックすると、ArgumentExceptionまたはその子が発生します。

あなたのメソッドの中で信頼できないものを呼び出し、奇妙な結果を受け取った場合は、おそらく "oh、bug!bug!"で失敗するよりも意味のあるものを発生させるでしょう。バグ本当に、何ですか?私はむしろ操作の文脈で意味のある何かを上げたいと思う。

ビジネスルールのために投げなければならない場合は、アカウントを無効にするように求められ、パラメータは正しいと言いますが、このアカウントが既に無効であることがわかっている間は、無効ですInvalidOperationExceptionが実行されるため、.NETでこの「汎用」例外が発生します。

これで、ThisIsABugExceptionやそれに類するものを発生させたくないのです。

+0

'すべてのパラメータが正しいとすれば、なぜメソッド自体のロジックが正しいのでしょうか? ' - それはまさにポイントです:実行時に、メソッドは正しいかどうかを(健全性チェックによって)検出しますつまり、開発者だけが修正できるバグが含まれています。 – Heinzi

1

問題のある状態が発生したアプリケーションレイヤーを本質的に識別するカスタム例外タイプを定義して投げることをお勧めします。また、ロジックや状態に関連する問題を示したり、カスタムタイプとして再利用したりする、多くのタイプの例外をキャッチすることをお勧めします。そうでない場合、誰かがあなたのメソッドを呼び出し、ArgumentExceptionがスローされた場合、呼び出し元は、無効な引数をコードに渡した結果であるのか、コードに内部的な問題があるのか​​を知らないでしょう。関数インライン化のようなもののため、StackTraceはコールチェーンに含まれるすべてのメソッドをリストしていないことに注意してください。

関連する問題