代码合同静态检查无法正常工作?

时间:2011-02-21 15:17:10

标签: c# .net code-contracts

我在构造函数中创建了一个带有代码契约的类.CodeTypes有一个字符串属性列表。

Contract.Requires(type == CodeTypes.AdmitDx1 || type == CodeTypes.AdmitDx2
|| type == CodeTypes.AdmitDx3 || type == CodeTypes.DX 
|| type == CodeTypes.CPT || type == CodeTypes.HCPCS
|| type == CodeTypes.PX);

之后警告出现在我使用这个类的地方,因为放入了不同的值。到目前为止一直很好。

然后我去了一段代码,其中有一个投诉,并添加了if语句的反面并抛出异常。

警告仍然存在。

然后我在if语句的反面添加了一个return语句。

警告仍然存在。

然后我把一个大的if / else放在只有合同中的条件才被调用的地方。

警告仍然存在。

然后,我用一个带有该条件的if语句包围了合同。

警告消失了。

这里发生了什么?我预计前3个选项可以使用,我真的很想使用选项1.最好的方法是什么?

在CreateCodeFromType:

的构造函数中编辑合同存在的调用代码
//Type is an XElement that is passed into the method as a parameter
    if (type == null || (type.Value != CodeTypes.AdmitDx1 && type.Value != CodeTypes.AdmitDx2
    && type.Value != CodeTypes.AdmitDx3 && type.Value != CodeTypes.DX
    && type.Value != CodeTypes.CPT && type.Value != CodeTypes.HCPCS
    && type.Value != CodeTypes.PX))
    {
    throw new ValidationException("Type is invalid.");
    }
    else
    {
    var newCode = (new CreateCodeFromType(type.Value).CreateCode(term.Value));
    }

2 个答案:

答案 0 :(得分:1)

如果您提到的这段“其他代码”是另一种方法,而不是构造函数,那么您必须将参数保存到构造类型的字段中。在这种情况下,静态检查器无法在不满足条件时基于抛出或返回来检查任何内容,因为在满足条件之后,另一个线程可能会以这样的方式更改字段以使条件失败。要防止出现此类警告,请使用ContractInvariantMethodAttribute

如果这段代码仍在构造函数中,我无法想到静态检查器无法省略警告的任何原因(但是,如果你已经拥有{{1},为什么要使用if-statements前提条件?)。在那种情况下,我会责怪静态检查器的不完美,就像斯蒂芬一样。

编辑:举个例子,我可以看到错误。

我声明静态检查程序无法保证任何字段,因为其他线程可能会弄乱这些字段。 type.Value是一个字段,因此静态检查器警告您可能违反合同是合乎逻辑的。我甚至会在你声称它消失的情况下发出警告(或者我误解了你)。要解决这个问题,请创建一个局部变量,然后你就会得到静态检查器可以推理的东西。 请尝试以下方法:

Contract.Requires

或者如果您想使用合同,请使用

if (type == null) throw new ArgumentNullException();
var xElementValue = type.Value;
if(xElementValue != CodeTypes.AdmitDx1 && xElementValue != CodeTypes.AdmitDx2
&& xElementValue != CodeTypes.AdmitDx3 && xElementValuee != CodeTypes.DX
&& xElementValue != CodeTypes.CPT && xElementValue != CodeTypes.HCPCS
&& xElementValue != CodeTypes.PX) throw new ValidationException("Type is invalid.");
//And now you should be able to give xElementValue as argument without receiving warnings. 

我希望警告不会显示出这些解决方案中的任何一种。

答案 1 :(得分:0)

静态检查器并不完美。它仍处于开发阶段,即使它已经完成,它也无法知道所有内容

现在,您可以使用Contract.Assume为静态检查器提供一个提示并传递条件。

另外,请及时了解CC版本。他们目前在1.4.31130.0并计划很快发布另一个版本。在开发的这个阶段,静态检查器会看到每个版本的增量改进。