关于价值类型的代码合约

时间:2013-04-15 21:24:13

标签: c# c#-4.0 clr code-contracts

我刚开始玩代码合约,虽然很有希望,但它们似乎在价值类型方面有一些限制。例如:

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中将这种事物列为已知问题,但似乎很明显不能作为遗漏。我错过了什么吗?

2 个答案:

答案 0 :(得分:0)

原来问题是结构中指定的不变量。如果删除不变量,则会出现预期的错误。与MS的文档相反,静态检查器似乎确实考虑了结构不变量。

答案 1 :(得分:0)

你的getter合同中有一些奇怪的Value属性。你递归地要求this.Value!= null。我确定你的意思是其他的,例如。

Contract.Ensures( Contract.Result<T>() != null );

通过该修复,规范对我来说看起来非常合理。检查器(包括运行时)的限制是您始终可以创建结构的默认值,我们无法检查这些默认值的不变量。因此,检查是模块化默认值的构造。