2010-12-15 6 views
17

、私がnull引数をチェックするための4つの方法を考えることができます。前提条件をテストするためのさまざまな方法の長所と短所を教えてください。私の頭の上オフ

Debug.Assert(context != null); 
Contract.Assert(context != null); 
Contract.Requires(context != null); 
if (context == null) throw new ArgumentNullException("context"); 

私は私が最後の方法を常に使用しましたが、私はちょうどContract.Requiresを使用したコードスニペットを見て、どの慣れていない。 各メソッドの長所と短所は何ですか?他の方法はありますか? ReSharperの/ワット VS2010で


  • Contract.Assertは式が常に真であることを私に警告し(それは知っているどのように、私は非常にわからない...のHttpContextがnullにすることはできませんか? )、
  • Contract.Requiresはフェードアウトし、それは私がすべてのcontext != nullに最後の方法を変更した場合、コンパイラは(私があるため、元の理由により、それはnullになることはありませんと仮定)メソッドを呼び出し、そして
  • ません私に語っますコードfolloウィングが消えて、コードが発見的に到達できないことがわかります。

だから、最後の3つの方法は、VS静的チェッカーに組み込まれている何らかのインテリジェンスを持っているようで、Debug.Assertはちょうどダムです。

+0

質問は不明です。あなたは実際にそれらをすべて一度に使用しようとしていますか? –

+0

@Matthew:どうしたらいいのか分かりません...いいえ、私はそれらを一度に使うつもりはありません。私はヌルを確認できるさまざまな方法を説明するためにコードスニペットを作成しました。 – mpen

+0

それは私が残りの質問から考えたものですが、あなたが使った構文表現は奇妙でした。 –

答えて

12

私の推測では、そのコンテキストを必要とするIHttpHandler.ProcessRequestというインタフェースに契約が適用されていると思います!= null。インタフェースコントラクトは実装者によって継承されるため、Requiresを繰り返す必要はありません。実際には、インタフェース契約に関連する要件に限定されているため、追加のRequires文を追加することはできません。

契約義務の指定とヌルチェックの単純な実行を区別することが重要だと思います。 APIを正しく使用していることをデベロッパーに通知する方法として、実行時にヌルチェックを実装して例外をスローすることができます。一方、契約式は、実際にはメタデータの一種であり、これは契約書書換担当者(以前は手作業で実装されていた実行時例外を導入するため)だけでなく、推論に使用できる静的アナライザーアプリケーションの静的な正確さについて

つまり、コードコントラクトと静的解析を積極的に使用している環境で作業している場合、静的解析を利用するには、アサーションを契約書式に置くことが望ましいです。静的分析を使用していなくても、契約を使用することで、後で利用できるようにドアを開いたままにすることができます。注意すべき主な点は、書き換えを実行するようにプロジェクトを構成したかどうかです。それ以外の場合は、契約によって実行時の例外が発生することはありません。 、コメンターが言ったことにアサートとの違いを詳しく説明したとし、必要にするに


は次のとおりです。

  • Contract.Assert式が契約リライターと静的アナライザによるアサーションに変換されます既存の証拠に基づいて表現を証明しようとします。証明できない場合は、静的解析警告が表示されます。
  • Contract.Assume式は(私が知る限りは)コントラクトリライタでは無視されますが、スタティックアナライザは静的解析で考慮できる新しい証拠としてスタティックアナライザによって解釈されます。契約する。仮定は、必要な推論を行うための洗練さが欠けている場合や、コントラクトで装飾されていないコードと相互運用する場合の両方で、静的分析で「ギャップを埋める」と仮定します。特定の関数呼び出しはnull以外の結果を返します。
  • Contract.Requiresは、メソッドが呼び出されたときに常に真でなければならない条件です。メソッドのパラメータの制約(最も一般的です)や、オブジェクトの公開状態の制約(たとえば、InitializedがTrueの場合にのみメソッドを呼び出すことができます)などがあります。クラスのユーザーは、オブジェクトを使用するときにInitializedをチェックするか、そうでない場合はエラーを適切に処理するかを選択するか、独自の制約やクラス不変式を作成して初期化が実際に起こったことを明確にします。
+0

ですから、「Contract.Assert」と「Contract.Requires」の違いはどういうものでしょうか? – mpen

+2

@Ralph: 'Contract.Requires'は、メソッドが呼び出されたときに真であるべきことを示し、' Contract.Assert'はメソッドの途中で中間の状態をチェックします。適切な場所に 'Contract.Assert'を追加することで、スタティックアナライザが独自にコードを管理できない場合、コードが正しいことを証明するのに役立ちます。 –

+3

実際、静的チェッカーはContract.Assumeの恩恵を受けるだけです。このメソッドは、実行時にContract.Assertのように動作しますが、静的チェッカーに試行しないように指示し、統計的にこれを証明します。 – koenmetsu

2

最初の方法は、決して存在しないはずのヌル条件をテストするのに適しています。つまり、開発中に予期せずnullに設定されないようにするためにこのメソッドを使用します。エラー処理は行われないため、リリースされた製品でnull条件を処理する場合は適切ではありません。

私は2番目と3番目のバージョンは、どのような方法でも問題を処理しない点で似ていると言います。

一般に、最終製品で変数が実際にnullになる可能性がある場合、最後のバージョンが使用されます。あなたは特別な扱いをすることもできますし、それだけで例外を起こすこともできます。

+1

実際に、第2および第3の方法は、コンパイル時にそれらを真実にしようとするために静的解析を使用します。 –

+0

@Anon:しかし、静的アナライザは、コンパイル時にすべてのnull例外を捕まえることができません。例外を発生させたり、クラッシュさせたり、何もしたり、何をしたりしませんか? – mpen

+1

@Ralph:スタティック・アナライザが何かを証明できない場合(場合によっては契約が失敗することは示されませんが、どちらかが正しいと証明できないことは証明できません)、コンパイル警告を表示しますエラー)、それをアサーションに置き換えます。 –

関連する問題