2

プロジェクトのプロパティでランタイム コントラクト チェックを無効にするとすぐに、コントラクト クラスに対して FxCop 違反がスローされます (インターフェイスを介してコントラクトを実装し、抽象クラスでコントラクトを定義すると仮定します)。

ランタイム コントラクト チェックを再度有効にすると、すべての違反が消えます。

これの理由は何ですか?

次のような違反:

CA1811 ObjectInvariant には上流の呼び出し元がないようです

CA1033 MyClassContract を封印する

コントラクト クラスは抽象でなければならないため、意味がありません。

4

1 に答える 1

6

わかりました、あなたの言いたいことがわかると思います。の代わりにプライベートメソッドという名前のケビンのAccountContracts名前のようなクラスがあります:MyClassContractObjectInvariantsInvariants

[ContractClassFor(typeof(IAccount))]
public abstract class MyClassContract : IAccount
{
    public abstract double Balance { get; }

    void IAccount.Deposit(double amount)
    {
        Contract.Requires(amount >= 0.0d);

        //throw new NotImplementedException();
    }

    bool IAccount.Withdraw(double amount)
    {
        Contract.Requires(amount >= 0.0d);
        Contract.Requires(amount <= Balance);

        throw new NotImplementedException();
    }

    [ContractInvariantMethod]
    private void ObjectInvariants()
    {
        Contract.Invariant(Balance >= 0.0d);
    }
}

FxCopy とコード分析は、コンパイル後の分析を行います。バイナリ、つまりビルドによって生成された中間言語 (IL) を分析します。Code Contracts は、抽象クラスから派生するだけでなく、メソッドを少なくとも 1 回MyClassContract呼び出すバイナリにコードを生成するという点で、コンパイル後の織り方を行います。ObjectInvariantsコード コントラクトを「オフ」にすると、このコードが生成されなくなるため、FxCop とコード分析では、メソッドから派生したものやメソッドMyClassContractを使用するものは何も表示されずObjectInvariants、警告が表示されます。の場合MyClassContract、そこから派生するものは何もないため、封印することができ (これにより、特定の状況下でコンパイラがわずかに最適化するのに役立ちます)、将来のクラスの保守が容易になります (何もできません)。から派生するため、より自由に変更できます-少なくともそれが一般的なコンセンサスです)。

もちろん、警告なしでコードをそのまま残したい場合は、抑制ファイルでこれらの警告を抑制することができます。また、コンパイラ定数を含めてコードを囲み、コード コントラクトを使用しないときにコンパイルを回避し、コード コントラクトを有効にするときにその定数をビルド設定に含めることもできます。例えば:

#if CODE_CONTRACTS
//...
#endif

CODE_CONTRACTSコード コントラクトを有効にし、プロジェクトのビルド プロパティで宣言する特定のビルド構成を使用できるため、通常は新しいビルド構成を作成するのが最も簡単です。

于 2012-09-10T21:51:23.780 に答える