Выбрасывание исключения vs. Contract.Requires <T>?

Мне интересно, следует ли мне делать исключения или вызывать Contract.Requires<TException>

Например:

public static void Function(String str)
{
    if (str == null) throw new ArgumentNullException("str", "Input string cannot be null.");

    // ...
}

против

public static void Function(String str)
{
    Contract.Requires<ArgumentNullException>(str != null, "Input string cannot be null.");

    // ...
}

Так как Contract.Requires<TException> не требует символа CONTRACTS_FULL, который я могу сохранить в своих выпусках.

Это мое мнение:

Кон: Вы не можете вызвать перегруженную версию конструктора настраиваемого типа исключения. Нет простого способа передать дополнительные параметры конструктору.

Pro: Поддержка статических инструментов (например, информирование вызывающего абонента о нарушении контракта).

Какой я должен использовать и для какой ситуации?

Ответы

Ответ 1

Основной компромисс между if-then-throw и Requires<TException>, как описано в руководстве пользователя CodeContract, - это то, как вы строите свои биты релиза.

Случай 1. Вы используете только if-then-throw, no Requires<TException>. В этом случае вы можете создавать свои разрядные биты без использования инструментов контракта на вашей dll/exe. Преимущество состоит в том, что у вас есть более быстрая сборка и нет риска, что инструмент вводит ошибки. Второе преимущество заключается в том, что члены команды могут отказаться от использования инструментов CodeContract. Недостатки в том, что вы не получаете никакого наследования контрактов, и ваши контракты не обязательно видны инструментам (если вы не используете EndContract). Вы указываете этот случай, используя режим сборки: Пользовательская проверка параметров

Case2: вы решаете всегда запускать инструменты CodeContract на своих битах релиза. Это позволяет использовать Requires<TException>, и вы получаете наследование контрактов, включая инструменты интерфейсов и т.д. Ваши контракты чисты и распознаются инструментом. Недостатком является то, что каждый, кто строит ваш код, должен иметь установленные инструменты CodeContracts. Вы указываете этот случай, используя режим сборки: Стандартный в области свойств Контракт.

Надеюсь, что это ясно.

Ответ 2

Я не уверен, что между этими двумя подходами существуют какие-то разрушающие землю различия, но вот две причины, по которым я предпочитаю контракты...

1) Код намного опрятен, так как вы пишете оператор в верхней части метода, который показывает предположения, на которых основан метод. Вы не засоряете код с реализацией того, что произойдет, если это допущение нарушено.

2) Вы получаете преимущество Visual Studio, которое набирает контракты на код при написании кода и дает вам подсказки относительно того, какой метод вы собираетесь вызывать. Это поможет вам убедиться, что вы отправляете действительные параметры метода, не переходя к определению метода, чтобы проверить там код.

Как только код скомпилирован и запущен, я не думаю, что существуют существенные различия.

Надеюсь, что это поможет.