c# - 在 C# 代码合约中使用纯函数时的静态验证限制?

标签 c# code-contracts

我正在尝试使用代码契约静态验证以下基于数组的堆栈的部分实现。方法Pop()使用纯函数IsNotEmpty()以确保后续数组访问将处于/高于下限。静态验证器失败并建议我添加前提条件 Contract.Requires(0 <= this.top) .

任何人都可以解释为什么验证者无法证明数组访问相对于给定合约的下限是有效的 IsNotEmpty()

起初我以为Contract.Requires(IsNotEmpty())方法可能不正确,因为子类可以覆盖 IsNotEmpty() 。但是,如果我将类标记为sealed,验证器仍然无法证明数组访问是有效的。 .

更新:如果我更改 IsNotEmpty()对于只读属性,验证按预期成功。这就提出了一个问题:如何/为什么对只读属性和纯函数进行不同的处理?

class StackAr<T>
{
    private T[] data;
    private int capacity;

    /// <summary>
    /// the index of the top array element
    /// </summary>
    private int top;

    [ContractInvariantMethod]
    private void ObjectInvariant()
    {
        Contract.Invariant(data != null);
        Contract.Invariant(top < capacity);
        Contract.Invariant(top >= -1);
        Contract.Invariant(capacity == data.Length);
    }

    public StackAr(int capacity)
    {
        Contract.Requires(capacity > 0);
        this.capacity = capacity;
        this.data = new T[capacity];
        top = -1;
    }

    [Pure]
    public bool IsNotEmpty()
    {
        return 0 <= this.top;
    }

    public T Pop()
    {
        Contract.Requires(IsNotEmpty());

        //CodeContracts: Suggested precondition: 
        //Contract.Requires(0 <= this.top);

        T element = data[top];
        top--;
        return element;
    }
}

最佳答案

这应该可以解决问题:

[Pure]
public bool IsNotEmpty() {
    Contract.Ensures(Contract.Result<bool>() && 0 <= this.top || !Contract.Result<bool>() && 0 > this.top);
    return 0 <= this.top;
}

请参阅代码合约论坛上的此帖子以获取更多信息:Calling a method in Contract.Requires

编辑:

这个问题的另一个解决方案,如上面链接的线程中提到的,是 -infer 命令行选项:

Now, inferring the post condition of this method is possible, and in fact we do have the option to do so: try to add -infer ensures on the extra options line in the contract property pane for the static checker.

我已经检查过,这确实解决了问题。如果您查看code contracts manual ,您会看到默认选项是仅推断属性后置条件。通过使用此开关,您也可以告诉它尝试推断方法的后置条件:

-infer (requires + propertyensures + methodensures) (default=propertyensures)

关于c# - 在 C# 代码合约中使用纯函数时的静态验证限制?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3695627/

相关文章:

c# - Linq Group 按日期和对象列表列出

.net - 我需要安装什么才能使代码合约与 2010 兼容

c# - 尝试在 azure 存储帐户/Blob 上设置 cors 时出现无尽错误

c# - 如何从 C# Windows 应用程序向 PHP 服务器发送包含对象数组的 POST 请求?

.net - 带有接口(interface)的代码契约(Contract) : "Method Invocation skipped. Compiler will generate method invocation because the method is conditional... [...]"

c# - Contract.Exists 如何增加值(value)?

.net - 如何使用代码契约进行单元测试

security - 代码契约(Contract)是否应该用于安全性?

c# - webapi2 owin,我无法启动项目

c# - 嵌套列表,我如何使用 lambda 表达式来做到这一点?