Выбрасывание исключения 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, которое набирает контракты на код при написании кода и дает вам подсказки относительно того, какой метод вы собираетесь вызывать. Это поможет вам убедиться, что вы отправляете действительные параметры метода, не переходя к определению метода, чтобы проверить там код.
Как только код скомпилирован и запущен, я не думаю, что существуют существенные различия.
Надеюсь, что это поможет.