【发布时间】:2010-10-06 16:10:01
【问题描述】:
假设我有一个提供一些内部线程同步的自定义集合类。例如,简化的 Add 方法可能如下所示:
public void Add(T item)
{
_lock.EnterWriteLock();
try
{
_items.Add(item);
}
finally
{
_lock.ExitWriteLock();
}
}
最新的代码合同抱怨CodeContracts: ensures unproven: this.Count >= Contract.OldValue(this.Count)。问题是这真的无法证明。我可以确保,在内部,在锁内,Count 将大于其先前的值。但是,在方法退出时,我无法确保这一点。在退出锁之后,在方法完成之前,另一个线程可能会发出两个 Removes(可能是不同的元素),从而使合约无效。
这里的基本问题是,只有在特定的锁定上下文中,并且只有在整个应用程序中一致地使用锁定来对集合的所有访问时,才能认为集合合同是有效的。我的集合必须从多个线程中使用(非冲突的添加和删除是一个有效的用例),但我仍然想实现ICollection<T>。我是否应该简单地假装我可以通过假设满足这个确保要求,即使我知道我不能?令我震惊的是,没有一个 BCL 集合实际上也可以确保这一点。
编辑:
根据进一步的调查,听起来最大的问题是合约重写器可能会引入不正确的断言,从而导致运行时失败。基于此,我认为我唯一的选择是将我的接口实现限制为IEnumerable<T>,因为ICollection<T> 上的合同意味着实现类不能提供内部线程同步(访问必须始终在外部同步。)这是可以接受的我的特殊情况(所有希望改变集合的客户都直接知道类类型),但我很想知道是否有其他解决方案。
【问题讨论】:
-
如果您使用假设,您可能仍然会遇到运行时合约错误。
标签: c# static-analysis code-contracts