我正在尝试将代码契约应用于我的代码,我遇到了一个令人困惑的问题。
这段代码无法满足合同,但除非我真的很厚,否则我希望它能够轻松分析id
在返回时必须有一个值
if (id == null) throw new InvalidOperationException(string.Format("{0} '{1}' does not yet have an identity", typeof(T).Name, entity)); return id.Value;
答案 0 :(得分:6)
我已经了解了这种行为,并且这不是Code Contract的错。
我在ILSpy中打开了生成的程序集,这是生成的代码:
public Guid Id
{
get
{
Guid? guid = this.id;
if (!guid.HasValue)
{
throw new InvalidOperationException();
}
guid = this.id;
return guid.Value;
}
}
正在将实例变量id
复制到局部变量,并且在条件块之后将此局部变量重置回其原始值。现在很明显为什么Code Contracts显示合同违规错误,但仍然让我感到困惑,为什么代码被重写为这种形式。我做了一些实验,并将Code Contracts完全从项目中删除,很明显这是标准的C#编译器行为,但为什么呢?
这个秘密似乎是由于我在原始问题中不小心遗漏的一个小细节。 id
实例变量声明为readonly
,这似乎是导致编译器添加临时guid
变量的原因。
我必须承认,我仍然感到困惑,为什么编译器认为需要这样做以确保id
的不变性保证,但我会继续挖掘......
答案 1 :(得分:1)
您可以尝试将字段复制到本地值,并根据该本地值编写语句。证明者可能对字段保守,因为调用可能会改变字段值。
答案 2 :(得分:0)
它没有看到你的if throw支票作为其合约的一部分。试试这个:
if (id == null)
throw new InvalidOperationException(string.Format("{0} '{1}' does not yet have an identity", typeof(T).Name, entity));
Contract.EndContractBlock();
http://msdn.microsoft.com/en-us/library/system.diagnostics.contracts.contract.endcontractblock.aspx