【问题标题】:Using Contract.ForAll in Code Contracts在代码合同中使用 Contract.ForAll
【发布时间】:2011-03-07 11:59:33
【问题描述】:

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

[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 合同的接口),因此我在传递到 AddRequested 的子组上收到“需要未经证实:组!= null”错误。我是否正确使用了 ForAll 语法?如果是这样并且求解器根本不理解,是否有其他方法可以帮助求解器识别合同,或者我是否只需要在调用 GetAllGroups() 时使用 Assume?

【问题讨论】:

  • 最新版本已启用ForAll,你不妨试试看:)

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


【解决方案1】:

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

  1. 忽略警告。
  2. 在调用AddRequested()之前添加Contract.Assume(subGroup != null)
  3. 在调用AddRequested() 之前添加检查。也许是if (subGroup == null) throw new InvalidOperationException()if (subGroup != null) AddRequested(subGroup)

选项 1 并没有真正的帮助。选项 2 是有风险的,因为它会绕过 AddRequested() Requires 合同,即使 IUnboundTagGroup.GetAllGroups() 不再确保该后置条件。我会选择选项 3。

【讨论】:

  • 谢谢;我想我可能会使用 Assume,因为原始代码(合同前)没有空检查。它还清楚地标记了静态证明者需要“帮助”的各个地方,以便当证明者变得更强大时,希望我可以回去删除其中的一些。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-26
相关资源
最近更新 更多