为什么CodeContracts静态检查器建议我Contract.Assume(a)在我Contract.Ensure(a)之后?

时间:2013-06-30 07:39:52

标签: c# inheritance abstract-class code-contracts post-conditions

基本上,我有一个虚拟方法将某些强制性后置条件传播到子类。这是一个简化版本和静态检查器生成的奇怪警告(编辑 - 我的例子不完整。现在就是这样):

public abstract class InitializerClass
{
    protected bool _initialized

    public bool IsInitialized
    {
        get { return _initialized; }
    }

    public virtual void Initialize()
    {
        //Warning CodeContracts: Missing precondition in an externally visible
        //method. Consider adding Contract.Requires(this.IsInitialized); for
        //parameter validation
        Contract.Ensures(IsInitialized);
    }
}

这是另一个类:

public abstract class OrderingClass
{
    protected bool _ordered

    public bool IsOrdered
    {
        get { return _ordered; }
    }

    public override void Initialize()
    {
        //Message CodeContracts: Suggested assume: Contract.Assume(this.IsOrdered);
        Contract.Ensures(IsOrdered);
    }
}

实际上,这两个警告都指向方法的结束大括号,在紧跟Contract.Ensure调用的行中。我的代码出了什么问题?

1 个答案:

答案 0 :(得分:0)

您收到此错误,因为代码合同无法验证调用Initialize()是否会导致IsInitialized返回true。这是因为Initialize()正文中没有将IsInitialized的值设置为true的代码,因此分析器会警告您代码假定IsInitialized是<{1}}进入true后,您应该明确这个前提条件。

有两种方法可以消除警告。

首先,添加建议的前提条件:

Initialize()

其次,将public virtual void Initialize() { Contract.Requires(IsInitialized); Contract.Ensures(IsInitialized); } 的值设置为IsInitialized

true

您需要向public virtual void Initialize() { IsInitialized = true; Contract.Ensures(IsInitialized); } 添加私有设置器才能使上述代码生效。

IsInitialized

简单地在public bool IsInitialized { get { return _initialized; } private set { __initialized = value; } } 中设置_initialized = true可能不会允许代码合同验证后置条件,因此添加私有设置器。但是,假设将以下合同添加到Initialize()可能会否定添加属性设置器的需要:

IsInitialized

出于同样的原因,您在public bool IsInitialized { get { Contract.Ensures(Contract.Result<bool>() ^ !_initialized); return _initialized; } } 收到警告。代码合同建议使用OrderingClass,因为您无法在替换中使用Contract.Assume()