你能把Code Contracts放在私人领域吗?

时间:2015-09-07 11:59:17

标签: c# field code-contracts

为了简单起见,我说我有一个私人字段来缓存我的收藏计数:

private int _count;

我想确保计数永远不会低于零。我可以在不变量中检查这个:

[ContractInvariantMethod]
private void invariant(){
    Contract.Invariant(_count >= 0);
}

然而,这只会在退出公共方法时遇到错误 - 而不是在它发生时。该值可以通过更复杂的算法进行分配,因此获取失败的确切时间可能很有价值。

我可以将合同包装在这样的房产中:

public int Count {
    get {
        Contract.Ensures(Contract.Result<int>() >= 0);
        return _count;
    }
    private set {
        Contract.Requires(value >= 0);
        _count = value;
    }
}

但这并不能确保我不直接访问该字段,并且在内部更改值时会增加通过属性的额外开销。由于setter是私有的,我也不能将合同粘在接口上。

是否可以通过合同注释该字段以确保在设置时检查该字段?

2 个答案:

答案 0 :(得分:1)

我认为在性能和稳定性方面使用属性是最好的方法。

public int Count {
    get {
        Contract.Ensures(Contract.Result<int>() >= 0);
        return _count;
    }
    private set {
        Contract.Requires(value >= 0);
        _count = value;
    }
}
  

但这并不能确保我不直接访问该字段......

是的,但是您作为代码作者可以确保永远不会直接访问该字段。如果风险太大(大型团队,无纪律的程序员等),您可以将Count属性移动到具有更简单实现的基类。

  

...它在内部更改值时增加了通过属性的额外开销。

是的,你必须在性能和确保稳定性之间做出决定。如果您确实需要从性能时间中减去每个可能的毫秒,请考虑采用不同的方法来获取和设置此Count值,例如使用公共GetCount()和/或SetCount()方法替换公共属性(不确定方法是否正确)招致相同的开销有属性,我只是抛出一些想法。

答案 1 :(得分:0)

这似乎是possible using PostSharp's attribute Required

[Required]
private int _count;

他们给出了以下示例:

public class CustomerModel
{
    [Required]
    private string mFirstName = “Not filled in yet”;

    public void SetFirstName(string firstName)
    {
        mFirstName = firstName;
    }
}

然后说

  

在此示例中,firstName将在分配给mFirstName之前由Required合同验证。在字段上放置合同提供了验证字段的额外好处,无论它在何处设置。

值得注意的是,虽然这有效,但它并没有利用微软的代码合同。