假設我有一個自定義集合類,它提供了一些內部線程同步。例如,簡單的添加方法可能是這樣的:收集合同和線程
public void Add(T item)
{
_lock.EnterWriteLock();
try
{
_items.Add(item);
}
finally
{
_lock.ExitWriteLock();
}
}
最新的代碼契約抱怨CodeContracts: ensures unproven: this.Count >= Contract.OldValue(this.Count)
。問題是,這實在無法證明。我可以確保,在內部的鎖定內,Count會比先前的值大。但是,在方法退出時我無法確保這一點。鎖退出後,方法完成之前,另一個線程可以發出兩個刪除(可能是不同的元素),使合同無效。
這裏的根本問題是,集合合約只能在特定的鎖定上下文內被認爲是有效的,並且只有在整個應用程序中對所有集合的訪問一致地使用鎖定。我的集合必須從多個線程中使用(非衝突的Add和Remove是一個有效的用例),但我仍然想要實現ICollection<T>
。我是否應該簡單地假裝我能滿足這個要求,即使我知道我不能做到這一點,但可以確保要求。這讓我覺得BCL的所有收藏都無法真正確保這一點。
編輯:
基於一些進一步的調查,這聽起來像最大的問題是,該合同重寫可以引進不正確的斷言,導致運行時故障。基於此,我認爲我唯一的選擇是限制我的接口實現爲IEnumerable<T>
,因爲ICollection<T>
上的合同意味着實現類不能提供內部線程同步(訪問必須始終在外部進行同步。)這對於我的特殊情況是可以接受的(所有希望改變集合的客戶都會直接瞭解類的類型),但是我非常有興趣知道是否有其他解決方案。
如果您使用假設您仍然可能會收到運行時合同錯誤。 – 2012-02-10 15:09:21