代码契约是否未能发现 Nullable.HasValue 和 null 之间的明显关系?
我正在尝试将代码契约应用于我的代码,但遇到了一个令人困惑的问题。 这段代码未能满足合同要求,但除非我真的很厚,否则我希望它能够轻松分析 id
在返回时必须有一个值
if (id == null) throw new InvalidOperationException(string.Format("{0} '{1}' 尚无标识", typeof(T).Name,entity)); 返回 id.Value;
I am experimenting with applying Code Contracts to my code and I've hit a perplexing problem.
This code is failing to meet the contract but unless I'm being really thick I would expect it to be able to easily analyse that id
must have a value at the point of return
if (id == null) throw new InvalidOperationException(string.Format("{0} '{1}' does not yet have an identity", typeof(T).Name, entity)); return id.Value;
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我已经查清了这种行为的真相,这不是 Code Contract 的错。
我在 ILSpy 中打开生成的程序集,这是生成的代码:
实例变量
id
被复制到局部变量,并且该局部变量在条件块之后被重置回其原始值。现在,代码合同显示合同违规错误的原因已经很明显了,但它仍然让我困惑为什么代码要以这种形式重写。我做了更多的实验,并将代码契约从项目中完全删除,很明显这是标准的 C# 编译器行为,但为什么呢?这个秘密似乎是由于我在最初的问题中不小心遗漏了一个小细节。
id
实例变量被声明为readonly
,这似乎是导致编译器添加临时guid
变量的原因。我必须承认我仍然很困惑为什么编译器认为需要这样做以确保
id
的不变性保证,但我会继续挖掘......I've got to the bottom of this behaviour and it is not Code Contract's fault.
I opened the generated assembly in ILSpy and this is the code that is produced:
The instance variable
id
is being copied to a local variable and this local variable is being reset back to its original value after the condition block. Now it became obvious why Code Contracts is showing a contract violation error but it still left me confused why the code was being rewritten in this form. I did a little more experimentation and took Code Contracts out of the project altogether and it became apparent that this is standard C# compiler behaviour, but why?The secret appears to be due to a minor detail that I accidentally omitted from my original question. The
id
instance variable is declared asreadonly
and this seems to be responsible for causing the compiler to add the temporaryguid
variable.I must admit I'm still confused why the compiler feels it needs to do this to ensure the guarantee of immutability for
id
but I'll keep digging...您可以尝试将该字段复制到本地值并根据该本地值编写语句。证明者可能对字段持保守态度,因为调用可能会改变字段值。
You might try copying the field to a local value and writing the statements in terms of that local value. The prover may be conservative about fields, since it's possible that a call could mutate the field value.
它没有看到你的 if throw 检查作为其合同的一部分。请尝试以下操作:
http://msdn.microsoft .com/en-us/library/system.diagnostics.contracts.contract.endcontractblock.aspx
Its not seeing your if throw check as part of its contracts. Try this instead:
http://msdn.microsoft.com/en-us/library/system.diagnostics.contracts.contract.endcontractblock.aspx