Why does FXCop throw violations against Contract classes when runtime checking is disabled?

StackOverflow https://stackoverflow.com/questions/12300532

  •  30-06-2021
  •  | 
  •  

Domanda

As soon as you disable runtime contract checking in a project's properties, FxCop violations are thrown for the contract classes (assuming you implement contracts via an interface, then define the contract in an abstract class).

Re-enable runtime contract checking and all the violations disappear..

What is the reason for this?

Violations like:

CA1811 ObjectInvariant appears to have no upstream callers

and

CA1033 Make MyClassContract sealed

which don't make sense since contract classes must be abstract.

È stato utile?

Soluzione

Okay, I think I see what you mean. You have class like Kevin's AccountContracts named MyClassContract with a private method named ObjectInvariants instead of Invariants:

[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 and Code Analysis does post-compile analysis. It analyses the binary, in other words the Intermediate Language (IL) that got generated by the build. Code Contracts kind of does a post-compile weave in that it generates code into the binary that not only derives from your abstract class MyClassContract as well as invokes the ObjectInvariants method at least once. When you "turn off" Code Contracts, it no longer generates this code so FxCop and Code Analysis see nothing that derives from MyClassContract nor anything that uses ObjectInvariants method and thus warns you. In the case of MyClassContract, since nothing derives from it, it can be made sealed (which helps the compiler optimize slightly under certain circumstances) as well as makes the class easier to maintain in the future (nothing can derive from it, so you're more free to change it--at least that's the general consensus).

You can, of course, suppress those warnings in a suppression file, if you want the code to remain as is without the warnings. You could also include a compiler constant and surround the code to avoid it compling when not using code contracts and include that constant in the build settings when you enable code-contracts. For example:

#if CODE_CONTRACTS
//...
#endif

Creating a new build-config is usually the easiest thing for this because you can have a particular build configuration that both enables code contracts and declares CODE_CONTRACTS in the projects Build properties.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top