在代码合同中使用Contract.ForAll

时间:2010-06-23 19:25:38

标签: c# static-analysis code-contracts forall

好的,我还有另一个Code Contracts问题。我有一个接口方法的合同,看起来像这样(为清楚起见省略了其他方法):

[ContractClassFor(typeof(IUnboundTagGroup))]
public abstract class ContractForIUnboundTagGroup : IUnboundTagGroup
{
    public IUnboundTagGroup[] GetAllGroups()
    {
        Contract.Ensures(Contract.Result<IUnboundTagGroup[]>() != null);
        Contract.Ensures(Contract.ForAll(Contract.Result<IUnboundTagGroup[]>(), g => g != null));

        return null;
    }
}

我的代码使用的界面如下所示:

    public void AddRequested(IUnboundTagGroup group)
    {
            foreach (IUnboundTagGroup subGroup in group.GetAllGroups())
            {
                AddRequested(subGroup);
            }
            //Other stuff omitted
    }

AddRequested需要一个非空的输入参数(它实现了一个具有Requires契约的接口),所以我得到一个'requires unproven:group!= null'错误传递给{{1 }}。我正确使用ForAll语法吗?如果是这样且求解器根本不理解,是否有其他方法可以帮助求解器识别合同,或者我只需要在调用GetAllGroups()时使用Assume?

1 个答案:

答案 0 :(得分:10)

Code Contracts User Manual状态,“静态合同检查器尚未处理Quantiers ForAll或Exists。”在此之前,在我看来,选项是:

  1. 忽略警告。
  2. 在致电Contract.Assume(subGroup != null)之前添加AddRequested()
  3. 在致电AddRequested()之前添加支票。可能是if (subGroup == null) throw new InvalidOperationException()if (subGroup != null) AddRequested(subGroup)
  4. 选项1并没有真正帮助。备选方案2存在风险,因为即使AddRequested()不再确保后置条件,它也将绕过IUnboundTagGroup.GetAllGroups()要求合同。我选择3。