为了简单起见,我说我有一个私人字段来缓存我的收藏计数:
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是私有的,我也不能将合同粘在接口上。
是否可以通过合同注释该字段以确保在设置时检查该字段?
答案 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合同验证。在字段上放置合同提供了验证字段的额外好处,无论它在何处设置。
值得注意的是,虽然这有效,但它并没有利用微软的代码合同。