Как использовать контракты кода при выводе из интерфейсов, таких как IDictionary <T, U>? - PullRequest
7 голосов
/ 03 октября 2010

Один класс, который я пишу, реализует IDictionary<string, object>. В моей реализации CopyTo я хотел бы использовать кодовые контракты: например, Contract.Requires<ArgumentNullException>(array != null).

Но я получаю это предупреждение (с некоторыми пространствами имен, удаленными для удобства чтения):

Метод 'LuaDictionary.CopyTo(KeyValuePair<String,Object>[],Int32)' реализует интерфейсный метод 'ICollection<KeyValuePair<String,Object>>.CopyTo(KeyValuePair<String,Object>[],Int32)', поэтому не может добавить Requires.

Я вижу, что есть некоторые связанные вопросы, но все они, похоже, имеют отношение к интерфейсам, которые находятся под контролем пользователя. Очевидно, что IDictionary<T, U> не находится под моим контролем, поэтому я не могу комментировать его с помощью ContractClassFor или чего-либо подобного.

Так я просто не могу использовать здесь кодовые контракты? Если так ... большой облом ...

Ответы [ 2 ]

5 голосов
/ 07 октября 2010

Имейте в виду, что IDictionary<K,V> уже имеет это Requires:)

Вы можете просмотреть существующие библиотеки DLL контрактов для классов: C:\Program Files (x86)\Microsoft\Contracts.

Если вы откроете mscorlib.Contracts.dll с помощью Reflector, вы сможете просмотреть контракты для классов коллекции; CopyTo имеет следующее:

public void CopyTo(T[] array, int arrayIndex)
{
    Contract.Requires((bool)(array != null), null, "array != null");
    Contract.Requires((bool)(arrayIndex >= 0), null, "arrayIndex >= 0");
    Contract.Requires((bool)((arrayIndex + this.Count) <= array.Length), null, "arrayIndex + this.Count  <= array.Length");
}
5 голосов
/ 03 октября 2010

Это облом, но понятно, потому что клиентский код, который использует экземпляры вашего класса как IDictionary<string, object>, не должен отвечать предварительным условиям, которые не ожидаются от IDictionary<string, object>.

Вы можете прочитать ответпредоставленный этому SO-вопросу , который ссылается и цитирует Руководство пользователя Code Contracts, и вы можете посмотреть эту статью , которая объясняет ситуацию таким образом, и продолжает предоставлятьпростой пример:

Обратите внимание, что принцип подстановки Лискова верен для контрактов кода во многом так же, как и для простых классов.Принципы Лискова гласят:

Подклассы всегда должны заменять свои базовые классы.

С точки зрения API контрактов кода это означает, что производный класс (иликласс, реализующий интерфейс на основе контракта), не должен ожидать больше предварительных условий в качестве родительского.

...