代码契约静态检查无法正常工作?
我在构造函数 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));
}
I made a class with a code contract in the constructor CodeTypes has a list of string properties.
Contract.Requires(type == CodeTypes.AdmitDx1 || type == CodeTypes.AdmitDx2
|| type == CodeTypes.AdmitDx3 || type == CodeTypes.DX
|| type == CodeTypes.CPT || type == CodeTypes.HCPCS
|| type == CodeTypes.PX);
After that warnings appeared where I was using this class because different values were put in. So far so good.
Then I went to a piece of the code where there was a complaint and added the opposite of the if statement and threw an exception.
The warning remained.
I then added a return statement on the opposite of the if statement.
The warning remained.
I then put a big if/else where the class was only called if the condition in the contract was meant.
The warning remained.
I then surrounded the contract with an if statement with that condition.
The warning disappeared.
What is going on here? I expected the 1st 3 options to work and I really wanted to use option 1. What is the best way to go about this?
Edit the calling Code the contract exists in the constructor of 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));
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
如果您提到的“其他代码段”位于另一个方法中,而不是构造函数中,那么您必须将参数保存到构造类型的字段中。在这种情况下,静态检查器无法在不满足条件时基于抛出或返回来检查任何内容,因为满足条件后,另一个线程可能会更改字段,从而导致条件失败。要防止在这种情况下出现警告,请使用
ContractInvariantMethodAttribute
。如果这段代码仍在构造函数中,我想不出静态检查器无法省略警告的任何原因(但话又说回来,如果您已经有了
Contract.Requires< /code> 前提条件?)。在这种情况下,我会责怪静态检查器的缺陷,就像斯蒂芬一样。
编辑:给出的例子我可以看到出了什么问题。
我说过静态检查器不能保证任何字段,因为其他线程可能会弄乱这些字段。 type.Value 是一个字段,因此静态检查器警告您可能违反合同是合乎逻辑的。我什至希望在您声称它消失的情况下出现警告(或者我误解了您)。为了解决这个问题,创建一个局部变量,然后你就得到了静态检查器可以推理的东西。
因此,请尝试以下操作:
或者,如果您想使用合同,请使用
“我希望这些解决方案中的任何一个都不会出现警告”。
If this "other piece of code" you mentioned is in another method, not the constructor, then you must have saved the arguments to fields on the constructed type. In that case the static checker can't check anything based on throwing or returning when a condition is not met, because after the conditions were met, another thread might change the fields in such a way that it would fail the conditions. To prevent the warnings in this case, use a
ContractInvariantMethodAttribute
.If this piece of code is still in the constructor I can't think of any reason why the static checker couldn't omit the warnings(but then again, why use if-statements if you already have the
Contract.Requires
precondition?). In that case I'd blame the imperfection of the static checker, like Stephen does too.EDIT: given the example I can see what's wrong.
I stated that the static checker can't guarantee anything of fields, since other threads might be messing with those fields. The type.Value is a field, so it is logical the static checker warns you of the possible breaking of the contract. I would even expect the warning in the case you claim it disappears(or I'm misinterpreting you). To solve this, create a local variable and then you've got a something the static checker can reason about.
So try the following:
Or if you want to use contracts, use
I hope the warnings don't show theirselves with either of these solutions.
静态检查器并不完美。它仍在开发中,即使完成后,它也无法了解一切。。
现在,您可以使用Contract.Assume 并传递条件向静态检查器提供提示。
另外,请及时了解 CC 版本的最新情况。目前版本为 1.4.31130.0,并计划很快发布另一个版本。在开发过程中,静态检查器在每个版本中都看到了增量改进。
The static checker is not perfect. It's still in development, and even when it's complete, it won't be able to know everything.
For now, you can give the static checker a hint using
Contract.Assume
and passing the condition.Also, keep up-to-date on CC releases. They are currently at 1.4.31130.0 and planning another release soon. At this point in the development, the static checker is seeing incremental improvements with each release.