为什么FXCop在禁用运行时检查时会违反Contract类?

Mal*_*ker 2 c# fxcop code-contracts

一旦在项目的属性中禁用运行时合同检查,就会为合同类抛出FxCop违规(假设您通过接口实现合同,然后在抽象类中定义合同).

重新启用运行时合同检查,所有违规都会消失.

这是什么原因?

违规行为:

CA1811 ObjectInvariant似乎没有上游调用者

CA1033使MyClassContract密封

这是没有意义的,因为合同类必须是抽象的.

Pet*_*hie 6

好吧,我想我明白你的意思了.你有类像凯文的AccountContracts命名MyClassContract与命名的专用方法ObjectInvariants代替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);
    }
}
Run Code Online (Sandbox Code Playgroud)

FxCopy和代码分析进行后编译分析.它分析二进制,换句话说,由构建生成的中间语言(IL).Code Contracts MyClassContract类似于编译后编织,因为它在二进制文件中生成代码,不仅从您的抽象类派生,而且ObjectInvariants至少调用一次方法.当您"关闭"代码合同时,它不再生成此代码,因此FxCop和代码分析不会看到MyClassContract任何使用ObjectInvariants方法的内容,也不会发现任何使用方法的内容,从而警告您.在这种情况下MyClassContract,因为没有任何东西来自它,它可以被密封(这有助于编译器在某些情况下稍微优化)以及使类在未来更容易维护(没有任何东西可以从它得到,所以你是更自由地改变它 - 至少这是普遍的共识.

当然,如果您希望代码保持原样而没有警告,您可以在抑制文件中禁止这些警告.您还可以包含编译器常量并围绕代码以避免在不使用代码协定时进行编译,并在启用代码协定时在构建设置中包含该常量.例如:

#if CODE_CONTRACTS
//...
#endif
Run Code Online (Sandbox Code Playgroud)

创建一个新的build-config通常是最简单的事情,因为你可以拥有一个特定的构建配置,它可以CODE_CONTRACTS在项目Build属性中启用代码契约和声明.