我打算使用新的.NET 4 Code Contracts 功能进行未来的开发。这让我想知道我们是否必须在一系列方法中冗余地指定等效的Contract.Requires(...)
语句。
我认为一个代码示例胜过千言万语:
public bool CrushGodzilla(string weapon, int velocity)
{
Contract.Requires(weapon != null);
// long code
return false;
}
public bool CrushGodzilla(string weapon)
{
Contract.Requires(weapon != null); // specify contract requirement here
// as well???
return this.CrushGodzilla(weapon, int.MaxValue);
}
对于运行时检查它并不重要,因为我们最终总是会遇到需求检查,如果失败我们会收到错误。
但是,当我们再次在第二次重载中没有指定合同要求时,这被认为是不好的做法吗?
此外,还有编译时检查的功能,还可能还有代码合同的设计时间检查。在Visual Studio 2010中,它似乎尚不适用于C#,但我认为有一些类似Spec#的语言已经可以使用。当我们编写代码来调用这样的方法时,这些引擎可能会给我们提示,我们的参数当前可以是null
。
所以我想知道这些引擎是否会一直分析调用堆栈,直到他们找到一个目前不满意的合同方法?
此外,here I learned about the difference between Contract.Requires(...)
and Contract.Assume(...)
。我想在这个问题的背景下还要考虑差异吗?
答案 0 :(得分:14)
我认为最佳做法是在每个公共方法上指定所有合同。合同不仅仅是“得到检查的东西” - 它也是有效的文档。如果你调用一个方法但不知道应用了什么合同,那么将合同失败降低是很奇怪的:这会暗示你正在调用的方法中的错误,而不是你的方法。
请注意,如果您在整个项目中使用C#4,则可以考虑使用可选参数和命名参数来避免这么多重载。如果您需要从不支持它们的语言调用代码,那么这没有用。
我强烈怀疑如果你没有在“默认”超载中指定合同,静态检查器( 现在是available for all versions of VS2010)会抱怨合同可能会失败,并且建议添加合同。
答案 1 :(得分:4)
此外,还有一个特色 编译时检查,可能 还设计时间检查代码 合同。在Visual Studio 2010中,C#似乎尚不可用......
它可用,但要使用它你必须使用VS2010 终极版本。
警告:这有点推测,但从我用它学到的东西看似是正确的;
您需要手动通过方法传播约束,就像您已经完成的那样。
代码合约可以从方法外部看到的唯一信息就是您所说的。它可以检查 in 方法中的假设和断言,但此分析不会传播。换句话说,CC无法“透视”您的方法,因此它不会自动知道CrushGodzilla(string)
需要weapon
为非空。
如果使用静态分析,它将在CrushGodzilla(string)
中执行检查,并使用有关weapon
的外部信息意识到CrushGodzilla(string,int)
不能为空将建议您添加Requires
非null前提条件。 (非传播的事实是,这些知识不会用于分析程序的其余部分。)
我实际上并没有发现静态分析器的任何文件,尽管已经看过了。