Предположим, у меня есть собственный класс коллекции, который обеспечивает некоторую внутреннюю синхронизацию потоков. Например, упрощенный метод 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 будет больше, чем его предыдущее значение. Я не могу гарантировать это, однако, на выходе из метода. После выхода из блокировки и до завершения метода другой поток может выполнить два удаления (вероятно, из разных элементов), что делает контракт недействительным.
Фундаментальная проблема здесь заключается в том, что контракты на коллекцию могут считаться действительными только в пределах определенного контекста блокировки и только в том случае, если блокировка используется последовательно во всем приложении для всего доступа к коллекции. Моя коллекция должна использоваться из нескольких потоков (при этом не конфликтующие Add и Remove являются допустимым вариантом использования), но я все же хотел бы реализовать ICollection<T>
. Должен ли я просто притворяться, что могу выполнить это требование с помощью Ассума, хотя знаю, что не могу? Меня поражает, что ни одна из коллекций BCL на самом деле не может этого гарантировать.
EDIT:
Судя по некоторым дальнейшим исследованиям, самая большая проблема заключается в том, что переписчик контрактов может вводить неверные утверждения, что приводит к сбоям во время выполнения. Исходя из этого, я думаю, что мой единственный вариант - ограничить реализацию моего интерфейса IEnumerable<T>
, поскольку контракт на ICollection<T>
подразумевает, что реализующий класс не может обеспечить синхронизацию внутреннего потока (доступ всегда должен быть синхронизирован извне.) Мой конкретный случай (все клиенты, которые хотят изменить коллекцию, знают о типе класса напрямую), но мне определенно интересно узнать, есть ли другие решения для этого.