2

2 つのオーバーロードを持つメソッドを定義するユーティリティ ライブラリを作成しているとします。

public static class MyClass
{
    public static void DoSomething(string myValue, bool myFlag)
    {
        Contract.Requires<ArgumentNullException>(myValue != null);
        CallExternalMethod(myValue);
        if(myFlag){
            AlsoCallOtherMethod(myValue);
        }        
    }

    public static void DoSomething(string myValue)
    {
        Contract.Requires<ArgumentNullException>(myValue != null);
        DoSomething(myValue, true);
    }
}

ベスト プラクティスとして、1 つのメソッドだけでロジックを定義し、オーバーロードを使用して既定のパラメーターを指定します (.Net 3.5、.Net 4 の既定値パラメーターは使用できません)。

ご覧のとおり、コントラクトを使用して入力も検証しています。

ロジックは最初の方法だけなので、2番目のコントラクトは役に立たないのですか?

実行時チェックに関しては、駄目なのはわかっていますが、静的チェッカーはどうでしょうか。私のパターンを理解するのに十分賢いですか?

4

1 に答える 1

2

私はBonyT の答えに完全に同意しません。

コード コントラクトは、型や名前と同様に、ドキュメントとメソッドのコントラクトの一部です。ユーザー/開発者が、他のメソッドのオーバーロードを呼び出すだけで他には何も呼び出さないと想定する理由はありません。どのコントラクトがメソッドに適用されるかを推測するゲームであってはなりません。引数または戻り値に制約がある場合は、コード コントラクトを使用して文書化します。たとえ内部的に (他の人には隠されている) 別のメソッドを呼び出すだけであってもです。

コード コントラクトを単なるアサーション ツールと考えてはなりません。制御フローは、引数をチェックする他のオーバーロードに実行されるため、ここで行う必要はありません。ドキュメントとして見る必要があります。

そして実際的なレベルでは、コード コントラクトを追加すると、生成する XML ドキュメントにもそれらのコントラクトが追加されます。また、静的チェッカーや Code Contracts Editor Extensions などのツールを使用して、コントラクトをユーザーに表示できます。Pascal Cuoq によるこの関連投稿Jon Skeet によるこの投稿には、他にもいくつかの適切な議論があります。

ただし、ランタイムの観点からは冗長です。実行時のオーバーヘッドについて: ほとんどのチェックは比較的小さく、パフォーマンスの問題はありません。一部のチェックはパフォーマンスに影響を与える可能性があります (特にコレクション、配列、および列挙型のチェック) が、これらはプロジェクトの [コード コントラクト] プロパティ ダイアログで個別に無効にすることができます (たとえば、リリース ビルドの場合)。コントラクト全般についても同じことが言えます。非常に重要な場合にパフォーマンスを向上させるために、必要なレベルまでチェックを下げることができます。コントラクト アセンブリをビルドしても、ユーザーは引き続き静的チェックを受けます。

要約する。冗長なRequiresとEnsuresを指定することの短所:

  • 同じ条件が 2 回以上チェックされる場合があります
  • 複数のチェックによるパフォーマンスへのわずかな悪影響 (無効にしない場合)
  • より多くの入力 (ただし、これらのスニペットを参照してください)

プロの:

  • コードのドキュメント
  • 生成された XML のドキュメント
  • コードのユーザーの静的チェッカーは期待どおりに機能します
  • Code Contracts Editor 拡張機能の動作
  • ArgumentExceptionfor Requires は、遠く離れたメソッドの代わりに呼び出されたメソッドで発生します
于 2012-07-27T12:01:38.540 に答える