我刚开始玩代码合约,虽然很有希望,但它们似乎在价值类型方面有一些限制。例如:
public struct Wrap<T>
where T : class
{
readonly T value;
public Wrap(T value)
{
Contract.Requires(value != null);
this.value = value;
}
public T Value
{
get
{
Contract.Requires(Value != null);
return value;
}
}
[Pure]
[ContractInvariantMethod]
void Invariant()
{
Contract.Invariant(value != null);
}
public static T BigError()
{
Contract.Ensures(Contract.Result<T>() != null);
var x = default(Wrap<T>);
Contract.Assert(x.Value != null);
return x.Value;
}
}
Wrap.BigError清楚地证明了这个问题。此示例编译并且ccheck验证4个断言,但断言在运行时将明显失败。其中一些断言是多余的,我插入它们只是确保验证者在指定点检查这些属性。
我没有在MS's docs for code contracts中将这种事物列为已知问题,但似乎很明显不能作为遗漏。我错过了什么吗?
答案 0 :(得分:0)
原来问题是结构中指定的不变量。如果删除不变量,则会出现预期的错误。与MS的文档相反,静态检查器似乎确实考虑了结构不变量。
答案 1 :(得分:0)
你的getter合同中有一些奇怪的Value属性。你递归地要求this.Value!= null。我确定你的意思是其他的,例如。
Contract.Ensures( Contract.Result<T>() != null );
通过该修复,规范对我来说看起来非常合理。检查器(包括运行时)的限制是您始终可以创建结构的默认值,我们无法检查这些默认值的不变量。因此,检查是模块化默认值的构造。