当不使用ccrewrite时(假设该项目是由未安装CC的其他开发人员构建的),
Contract.Requires<T>(cond)
是否会被静默剥离,还是会导致行为等同于if (!cond) { throw new T() }
? (我不在乎它是否是另一个方法或两个方法 - 但应该“始终检查”。)
我问,因为Contract.Requires<T>
的行为与Contract.Requires
不同,但我不确定“如何”或“何时”。
目标是替换公共合同 上的构造
if (x != null) throw new ArgumentNullException();
与CC兼容的版本,在构建步骤中不执行CC重写时仍会抛出异常。
虽然以上EndContractBlock
与“自定义参数验证”(即遗留合同模式)有效,但我想在项目中使用“标准合同要求”。
我相信可能是等价的,因为在“自定义参数验证”模式下,我无法使用Requires<T>
;如果总是要求检查没有等效性,那就明白为什么会很好。
我很好地失去了Requires
,Ensures
,并且在没有进行CC重写的情况下留下了非荣誉的不变合约方法和接口合约,因为我重视静态分析 - 但我需要这些总是有边界检查来争取保持CC。
答案 0 :(得分:3)
请参阅Code Contracts manual。它肯定会告诉您有关各种形式的代码合同检查的工作原理以及使用每个表单时需要设置的选项。
Contract.Requires(bool cond)
和Contract.Requires<TException>(bool cond)
之间有什么区别?要回答您的第一个问题,请参阅手册中的 2.1前提条件部分。简而言之,这是区别:
Contract.Requires(bool cond)
如果条件评估为Contract.ContractException
,则会抛出私有false
异常。你不能抓住这个例外(因为从你的角度看它是私人的) - 这是为了阻止捕捉和处理它,从而使合同变得毫无价值。
Contract.Requires<TException>(bool cond)
如果条件的计算结果为false
,则会抛出指定的TException
。如果不在所有版本上运行合同工具,则无法使用此表单。
ccrewrite
具体而言,在第20页上,在 5部分中。使用指南,它告诉您代码合同可以使用的所有不同形式的合同,它们如何工作以及每种合同的构建要求。
我将简要总结一下,但请下载手册并阅读。这很好,虽然没有任何完整 - 你必须做大量的实验来学习如何有效地使用代码合同。此外,如果您可以访问PluralSight,John Sonmez有一个名为Code Contracts的课程,这是一个很棒的入门课程;迈克尔佩里有一个很棒的课程叫做Provable Code。
如果您不需要在已发布的代码中签订合同,那么:
Contract.Requires
如果您需要对已发布的代码进行合同检查,您有两种选择:
Contract.Requires<TException>
(例如,您的图书馆用户将要调用的方法),您希望针对这些方法投放特定的例外情况,例如ArgumentException
。Contract.Requires
非公开 API方法 或 公共 您不想抛出特定异常的API方法 。if (cond) { throw new Exception(...) }
保护阻止Contracts.EndContractBlock()
块之后放置if (cond) { throw new Exception(...) }
行,以便代码合同知道这些是您的合同。Contract.Requires
作为合同。关于上述内容需要注意的一点是:在调试版本中,合同检查始终启用。如果您团队中的其他开发人员将构建此库,则他们还需要安装代码合同。
从第5.1.3节:强制项目使用合同构建:
如果您正在使用方案2(Requires⟨Exn⟩)并且您将源代码提供给其他开发人员,您可能需要提醒他们需要使用这些工具来构建您的源代码。如果是这样,您可以在结尾处插入以下代码段(在导入CSharp或VisualBasic目标之后):
<PropertyGroup> <CompileDependsOn>$(CompileDependsOn);CheckForCodeContracts</CompileDependsOn> </PropertyGroup> <Target Name="CheckForCodeContracts" Condition="'$(CodeContractsImported)' != 'true'"> <Error Text="Project requires Code Contracts: http://msdn.microsoft.com/en-us/devlabs/dd491992.aspx" /> </Target>
另请参阅第6.1节:装配模式,其中它告诉您自定义参数验证和标准合同要求之间的区别。本节非常清楚地表明合同重写器(ccrewrite
)总是在 Debug 版本上运行。