Использование Debug.Assert vs Code Contract

Когда мне нужно отлаживать.заселение кодовых контрактов или наоборот? Я хочу проверить предварительное условие для метода, и я смущен, чтобы выбрать один над другим. У меня есть модульные тесты, где я хочу протестировать сценарии отказа и ожидать исключения.

Хорошо ли использовать протокол Debug.Assert и Code по тому же методу. Если да, то каким будет порядок написания кода?

Debug.Assert(parameter!= null);
Contract.Requires<ArgumentNullException>(parameter != null, "parameter");

или

Contract.Requires<ArgumentNullException>(parameter != null, "parameter");
Debug.Assert(parameter!= null);

Есть ли какое-либо обоснование?

Ответ 1

Это разные вещи. Утверждение отладки выполняется только тогда, когда код компилируется как отладка и поэтому будет проверять/утверждать только при отладке. Идея состоит в том, чтобы использовать это для "проверок здравомыслия" для кода, который вы разрабатываете. Кодовые контракты могут использоваться как для отладки, так и для выпуска. Они уверяют, что предварительные и последующие условия методов соответствуют ожиданиям метода (соответствуют контракту). Существует также структура тестирования, которая обеспечивает аналогичную функциональность, предназначенную для проверки соответствия теста.

Используйте Debug.Assert, если вы хотите, чтобы определенные вещи были такими, какие вы ожидаете при разработке кода (и в дальнейшем развитии обслуживания).

Используйте контракты с кодом, если вы хотите убедиться, что условия выполняются как в отладке, так и в выпуске. Контракты также допускают определенные формы статического анализа, которые могут быть полезны при проверке правильности вашей программы.

Использовать утверждения структуры тестирования при создании модульных тестов.

Ответ 2

Лично я не использовал бы как Debug.Assert AND Code Contracts для принудительного применения предварительных условий во вновь написанном коде, так и контракты IMO Code Contractce Debug.Assert, поскольку они предлагают более полный набор чеков, не говоря уже о выгоде, которая может получить статическую проверку, которую можно выполнить , прежде чем код получит время выполнения. Сохранение повторяющихся предварительных проверок в Debug.Assert и Contracts будет громоздким.

Обоснование:

  • Вам не нужно перекодировать любые предварительные условия, которые вы могли бы закодировать в коде Debug.Assert или throw - вы можете сохранить существующий код проверки условий и завершить его с Contract.EndContractBlock()
  • Вы можете получить одинаковое неконтролируемое поведение режима выпуска, если System.Diagnostics.Debug построено без /d:DEBUG, если вы создаете с проверкой времени выполнения контракта, установленным на None. Ссылка 6.2.1 в Документах
  • Контракты позволяют разработчику быть более выразительным в коде, так как "почему" обнаружено недопустимое состояние - например, был ли он напрямую из-за внеполосного параметра (Contract.Requires). В противном случае Contract.Assert или Contract.Assume может проверять общее состояние, а "гарантированная правильность" состояния при выходе из метода может быть выражена с помощью Contract.Ensures. И Invariants выражают, что состояние должно храниться в любое время.
  • И лучше всего, статическая проверка может обеспечить соблюдение этих Контрактов по мере создания вашего кода - таким образом, у вас есть шанс подобрать ошибку через время разработки или запрограммировать время, вместо того, чтобы ждать времени выполнения. Контрактные проверки могут быть добавлены в вашу непрерывную интеграцию для поиска несоблюдения.

Одно предупреждение: если вы собираетесь писать Unit Tests, которые преднамеренно нарушают контракты, вам может потребоваться иметь дело с ContractException - Jon Skeet объясняет это хорошо здесь. например Подключите Contract.ContractFailed обработчик в тестовой настройке к обработчику, который вызывает SetHandled, а затем выдает публичное исключение, которое вы можете поймать и утвердить в своих UT.