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式が常に true であることを警告します (どのように知っているのか、よくわかりません... HttpContext を null にすることはできませんか?)、
  • Contract.Requiresフェードアウトし、コンパイラーがメソッドを呼び出さないことがわかります (前の理由により、null になることはないと思います)。
  • 最後のメソッドをcontext != null次のすべてのコードに変更すると、フェードアウトし、コードがヒューリスティックに到達できないことがわかります。

したがって、最後の 3 つのメソッドには、VS 静的チェッカーに何らかのインテリジェンスが組み込まれているようであり、Debug.Assert単に馬鹿げています。

4

2 に答える 2

12

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

契約上の義務を指定することと、単純に null チェックを実行することを区別することが重要だと思います。API を正しく使用していることを開発者に知らせる方法として、null チェックを実装し、実行時に例外をスローできます。一方、コントラクト式は、実際にはメタデータの形式であり、コントラクト リライター (以前は手動で実装されていたランタイム例外を導入するため) によって解釈できますが、静的アナライザーによって解釈することもできます。アプリケーションの静的な正確性について。

とはいえ、コード コントラクトと静的分析を積極的に使用している環境で作業している場合は、静的分析を利用するために、アサーションをコントラクト形式にすることをお勧めします。静的分析を使用していない場合でも、コントラクトを使用することで、後の利益のためにドアを開いたままにしておくことができます。注意すべき主な点は、書き換えを実行するようにプロジェクトを構成したかどうかです。そうしないと、期待どおりにコントラクトによって実行時例外が発生しません。


コメンターが言ったことを詳しく説明すると、Assert、Assume、およびRequiresの違いは次のとおりです。

  • Contract.Assert 式はコントラクト リライターによってアサーションに変換され、静的アナライザーは既存の証拠に基づいて式を証明しようとします。証明できない場合は、静的分析の警告が表示されます。
  • Contract.Assume 式は、(私の知る限り) コントラクト リライターによって無視されますが、静的アナライザーによって、静的分析で考慮できる新しい証拠として解釈されます。Contract.Assume は、静的分析の「ギャップを埋める」ために使用されます。これは、必要な推論を行うための高度さが欠けている場合、またはコントラクトで装飾されていないコードと相互運用する場合のいずれかです。 、特定の関数呼び出しが null 以外の結果を返すこと。
  • Contract.Requires は、メソッドが呼び出されたときに常に true でなければならない条件です。これらは、メソッドへのパラメーターに対する制約 (最も一般的なもの) であり、公開されているオブジェクトの状態に対する制約でもあります (たとえば、Initialized が True の場合にのみメソッドの呼び出しを許可する場合があります)。の制約により、クラスのユーザーは、オブジェクトを使用するときに Initialized をチェックする (そうでない場合はおそらくエラーを適切に処理する) か、独自の制約やクラスの不変条件を作成して、Initialization が実際に発生したことを明確にするようにプッシュされます。
于 2010-12-15T01:24:29.843 に答える
2

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

2 番目と 3 番目のバージョンは、問題をまったく処理しないという点で似ていると思います。

一般に、最終製品で変数が実際に null になる可能性がある場合は、最後のバージョンが使用されます。そこで特別な処理を行うか、行ったように例外を発生させることができます。

于 2010-12-15T01:24:38.143 に答える