一旦在项目属性中禁用运行时合约检查,就会为合约类引发FxCop冲突(假设您通过接口实现合约,然后在抽象类中定义合约)。
重新启用运行时合同检查,所有违规行为都将消失。。
这是什么原因?
违规行为,如:
CA1811 ObjectInvariant似乎没有上游呼叫者
和
CA1033使MyClassContract密封
这是没有意义的,因为契约类必须是抽象的。
好吧,我想我明白你的意思了。您有一个名为MyClassContract
的类,类似Kevin的AccountContracts
,它有一个名称为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);
}
}
FxCopy和代码分析进行编译后分析。它分析二进制文件,换句话说就是由构建生成的中间语言(IL)。代码契约有点像编译后的编织,它将代码生成到二进制文件中,该二进制文件不仅派生自抽象类MyClassContract
,而且至少调用ObjectInvariants
方法一次。当您"关闭"代码契约时,它将不再生成此代码,因此FxCop和代码分析不会看到任何从MyClassContract
派生的代码,也不会看到任何使用ObjectInvariants
方法的代码,从而向您发出警告。在MyClassContract
的情况下,由于没有任何派生自它,所以它可以被密封(这有助于编译器在某些情况下稍微优化),并使类在未来更容易维护(没有任何可以从它派生,所以您可以更自由地更改它——至少这是普遍的共识)。
当然,如果希望代码保持原样而不显示警告,则可以在禁止显示文件中禁止显示这些警告。您还可以在不使用代码约定时包含编译器常量并将代码包围以避免其编译,并在启用代码约定时将该常量包含在构建设置中。例如:
#if CODE_CONTRACTS
//...
#endif
创建一个新的构建配置通常是最简单的事情,因为您可以有一个特定的构建配置,它既启用代码约定,又在项目build属性中声明CODE_CONTRACTS
。