【发布时间】:2016-01-05 03:35:03
【问题描述】:
我最近在一个非常大的项目中添加了代码合同。在通过数百个警告添加断言以安抚检查器之后,我留下了一些似乎显然不正确的警告!这可能是我能做的最简单的例子(完整代码是here,如果您认为细节可能很重要):
protected Thing DoStuff(A a)
{
Contract.Requires(a != null);
//CodeContracts: Consider adding the postcondition Contract.Ensures(Contract.Result<Thing>() == null); to provide extra-documentation to the library clients
D outResult;
var result = DoSomething(a, out outResult);
if (result == null)
return null;
return new Thing(outResult, result);
}
这个建议显然是错误的(我有从这个函数返回非空值的单元测试来证明它)!唯一可能的方法是“DoSomething”也总是返回 null,但它没有就此提出任何建议。
编辑:我通过完全重写 DoSomething 方法以不使用输出结果(而是返回包含 outResult 和结果的元组)来解决上述问题。但是,我仍然有其他错误的警告需要解决,并且可能具有相同的根本原因。
其实这是两个问题:
- 我是不是做错了什么或遗漏了一些明显的东西?
- 假设 CC 完全是错误,我以后有什么办法可以缓解此类问题 - 至少隐藏警告!
【问题讨论】:
-
你试过
if (result == null) { return null; } else { return new Thing(output, result); }这个表格吗 -
刚刚试过,没有效果。
-
如果不是立即返回,而是将返回值分配给一个变量,结果会改变吗?合同代码可能会被一些人认为是拥有多个 return 语句的不良做法所抛出。我提出这个建议是因为我注意到第一个 return 语句返回 null。
-
如何形成一个结果为空或结果具有某些特定属性的合同
Contract.Ensures(Contract.Result<Thing>() == null || Contract.Result<Thing>().Result != null)。注意我无法从当前位置访问bitbucket,所以我不知道如何访问Thing的成员 -
我认为您可以右键单击错误列表中的警告并选择禁止它,这将为方法添加
SupressMessage属性。如果没有,那么您可以手动添加属性。查看this answer 中使用的示例。
标签: c# code-contracts