在Func<>上定义代码合约

时间:2014-03-06 23:56:27

标签: c# code-contracts

我正在尝试将Code Contracts集成到一些现有代码中,到目前为止大部分内容都很好。我面临的问题是我在一个接口上设置了合同,一个实现将实现委托给一个Func<>传递给类的构造函数,类似于以下内容:

[ContractClass(typeof(IFooContract))]
public interface IFoo
{
    object Bar();
}

[ContractClassFor(typeof(IFoo))]
public abstract class IFooContract : IFoo
{
    object IFoo.Bar()
    {
        Contract.Ensures(Contract.Result<object>() != null);
        throw new NotImplementedException();
    }
}

public class DelegatedFoo : IFoo
{
    public DelegatedFoo(Func<object> barImplementation)
    {
        Contract.Requires(barImplementation != null);
        _barImplementation = barImplementation;
    }
    private readonly Func<object> _barImplementation;

    [ContractInvariantMethod]
    private void ObjectInvariants()
    {
        Contract.Invariant(_barImplementation != null);
    }

    public object Bar()
    {
        //"ensures unproven: Contract.Result<object>() != null" here.
        return _barImplementation();
    }
}

静态分析器报告错误“确保未经证实:Contract.Result()!= null”。我可以在Func&lt;&gt;上定义合约吗? (以及Action&lt;&gt;的扩展名)?

这是最好的解决方案吗?

public class DelegatedFoo : IFoo
{
    public DelegatedFoo(Func<object> barImplementation)
    {
        Contract.Requires(barImplementation != null);
        _barImplementation = barImplementation;
    }
    private readonly Func<object> _barImplementation;

    [ContractInvariantMethod]
    private void ObjectInvariants()
    {
        Contract.Invariant(_barImplementation != null);
    }

    public object Bar()
    {
        var result = _barImplementation();
        Contract.Assume(result != null);
        return result;
    }
}

1 个答案:

答案 0 :(得分:0)

那么,总是是否可以控制传入的Func<object>个实例?如果是这样,Func<object>参数引用的每个函数都需要定义Contract.Ensures(Contract.Result<object>() != null)后置条件。

如果你有一个Action参数,那也是如此。

另外,我绝对不会使用Contract.Assume(result != null)。你确定你永远不会返回null吗?如果你做了会怎么样?请尝试将其更改为Contract.Assert(result != null)。如果您可以控制Func<object>参数并使用后置条件,那么您应该能够在public object Bar()方法上指定后置条件,并放弃对任何断言或假设的需要。

最后,您可能需要考虑将Contract.Ensures(_barImplementation == barImplementation)添加到DelegatedFoo的构造函数中,但我认为后置条件由定义的不变量覆盖。我总是喜欢明确 - 它肯定不会受到伤害,特别是在涉及静态分析仪的情况下。