Обеспечение ввода входных параметров в метод без множества «если» в начале метода?

Интересно, есть ли менее подробный способ проверки ввода в моих методах? Например, я обычно пишу такие вещи:

public string SomeFunction(string param1, int param2)
{
    if(string.IsNullOrEmpty(param1)){
        throw new ArgumentException("bla", "param1");
    }
    if(param2 < 0 || param2 > 100 || param2 == 53)
    {
         throw new ArgumentOutOfRangeException("eek", "param2");
    }
}

Интересно, есть ли способ установить ограничения на параметры и компилятор уже справился с этим для меня? Я считаю, что это называется «Контракт», и я помню, что Spec # должен это делать, но сейчас это экспериментальный исследовательский проект.

Поэтому я задаюсь вопросом: есть ли что-нибудь, что может обеспечить чистое применение ограничений (по крайней мере, простых и часто повторяющихся, таких как string.IsNullOrEmpty) для входных параметров для .net 3.5 SP1 и в идеале .net 3.0 уже?

11.12.2008 19:08:33
7 ОТВЕТОВ
РЕШЕНИЕ

Три слова: дизайн по контракту

Одна реализация для C # может быть найдена здесь: http://www.codeproject.com/KB/cs/designbycontract.aspx

2
11.12.2008 19:27:01

Ну, вы могли бы что-то сделать с АОП, посмотрите на PostSharp .

Это может быть использовано для вставки необходимого кода, но это добавляет некоторые накладные расходы, как на этапе компиляции, так и на скомпилированный код.

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

6
11.12.2008 19:25:37
Просто чтобы прояснить, они на самом деле не являются частью C # 4.0 - они находятся в .NET 4.0. Насколько я знаю, в них нет ничего конкретного языка. Отличная ссылка в блоге;)
Jon Skeet 11.12.2008 19:21:39

Вы можете ввести метод CheckParameter, чтобы у вас была только одна строка кода в исходном методе.

Что-то вроде этого:

public string SomeFunction(string param1, int param2)
{
    CheckParameterNotNull(param1);
    CheckParameterRange(param2, 0, 100, 53); 
...
}

Конечно, вам понадобится умный метод CheckParameter, чтобы соответствовать всем вашим случаям.

2
11.12.2008 19:50:12

Рассмотрим «Spec #» от Microsoft Research: http://research.microsoft.com/SpecSharp/

Он расширяет C #, чтобы вы могли определять контракты, и они вложили много усилий во внесение контрактов в BCL и прочее.

1
11.12.2008 20:02:03

Вы можете оставить весь код проверки параметров как есть, но затем делегировать реальную работу частной функции. Закрытая функция не будет проверять параметры, потому что она будет вызываться только публичной функцией-привратником.

private string InternalSomeFunction(string param1, int param2)
{
  /* implementation goes here */
}

public string SomeFunction(string param1, int param2)
{
  if (string.IsNullOrEmpty(param1)) {
    throw new ArgumentException("bla", "param1");
  }
  if (param2 < 0 || param2 > 100 || param2 == 53) {
    throw new ArgumentOutOfRangeException("eek", "param2");
  }
  return InternalSomeFunction(param1, param2);
}

Он такой же многословный, как и оригинал, но, по крайней мере, ваша основная функция не загромождена вещами, которые на самом деле не являются центральными для реализации метода.

С другой стороны, перемещая код проверки параметров от остальной части реализации, это также устраняет некоторые аспекты самодокументирования проверок. Когда вы смотрите InternalSomeMethod, например, больше нет напоминания, param1которое всегда будет действительной непустой строкой, так что вы или программист по техническому обслуживанию могут испытать желание добавить проверку для этого позже во внутреннем методе.

0
11.12.2008 23:44:11

Моделируя мир типов WebForms, вы можете использовать набор элементов управления ErrorProvider и прикрепить их к вашим критическим текстовым полям, флажкам и т. Д. Вы можете отменить проверки для этих полей всякий раз, когда пользователь меняет фокус, или как часто вы предпочитаете.

Затем вы можете создать метод IsFormValid, который будет проверять все ErrorProviders и возвращать простое значение True, если все ErrorProviders проверяются.

Тогда во всем вашем основном коде все, что вам нужно сделать, это обернуть вашу обработку вокруг ..

if (IsFormValid)
{
   // Processing Magic Goes here.
}

Приятно то, что у вас могут быть разные «допустимые» состояния в зависимости от того, что пытается выполнить конкретный метод. Конечно, поле номера телефона может быть недопустимым и отображать маленькую красную точку, но это не должно препятствовать запуску метода UpdateFirstLastName.

0
11.12.2008 23:58:24

Между тем, с тех пор, как задан этот вопрос, кодовые контракты эволюционировали, что выглядит как «Серебряная пуля».

Текущий CTP доступен здесь (для .net 3.5) и является частью .net 4.0.

0
26.05.2009 18:01:45