2015-03-21 2 views
7

Например, вы обычно не хотят параметры в конструкторе быть пустым, так что это очень нормально, чтобы увидеть некоторые вещи, какЛучший способ проверить нулевые параметры (Guard Морозы)

if (someArg == null) 
{ 
    throw new ArgumentNullException(nameof(someArg)); 
} 

if (otherArg == null) 
{ 
    throw new ArgumentNullException(nameof(otherArg)); 
} 

Это делает немного загромождать код.

Есть ли способ проверить аргумент списка аргументов лучше этого?

Что-то вроде «проверить все аргументы и бросить ArgumentNullException, если любой из них равен нуля, и предоставляет вам аргументы, которые были пустыми.

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

+2

Возможный дубликат [Отметьте параметры как НЕВОЗМОЖНЫЕ в C# /. NET?] (Http://stackoverflow.com/questions/291340/mark-parameters-as-not-nullable-in-c-net) –

+1

возможно поместить их все в массив объектов и перебрать их с помощью цикла foreach? вам нужно что-то подобное? – JoJo

+0

Обычно мы проверяем наши параметры в начале метода, как ваш фрагмент кода. Не только для null, но и для других бизнес-логических моделей поведения. Я не вижу никаких проблем с этим, если у вас слишком много параметров. По крайней мере, вы можете легко прочитать требования своего метода. – Andre

ответ

8
public static class Ensure 
{ 
    /// <summary> 
    /// Ensures that the specified argument is not null. 
    /// </summary> 
    /// <param name="argumentName">Name of the argument.</param> 
    /// <param name="argument">The argument.</param> 
    [DebuggerStepThrough] 
    [ContractAnnotation("halt <= argument:null")]   
    public static void ArgumentNotNull(object argument, [InvokerParameterName] string argumentName) 
    { 
     if (argument == null) 
     { 
      throw new ArgumentNullException(argumentName); 
     } 
    } 
} 

использование:

// C# < 6 
public Constructor([NotNull] object argument) 
{ 
    Ensure.ArgumentNotNull(foo, "foo"); 
    ... 
} 

// C# >= 6 
public Constructor([NotNull] object bar) 
{ 
    Ensure.ArgumentNotNull(bar, nameof(bar)); 
    ... 
} 

DebuggerStepThroughAttribute приходит очень удобно, так что в случае excpetion во время отладки (или когда я присоединить отладчик после исключение) Я не буду входить в метод ArgumentNotNull, но вместо этого в вызывающем методе, где имеет место нулевая ссылка actually.

Я использую ReSharper Contract Annotations.

  • ContractAnnotationAttribute убеждается, что я никогда не орфографические ошибки аргумент ("foo"), а также переименовывает его автоматически, если переименовать foo символ.
  • NotNullAttribute помогает ReSharper с анализом кода. Поэтому, если я сделаю new Constructor(null), если вы получите предупреждение от ReSharper, это приведет к исключению.
  • Если вы не хотите комментировать свой код напрямую, , вы также можете сделать то же самое с external XML-files, которое вы могли бы развернуть вместе с вашей библиотекой и чтобы пользователи могли ссылаться на них в своем ReShaprer.
8

Если у вас слишком много параметров в ваших конструкторах, вам лучше их пересмотреть, но это еще одна история.

Уменьшить шаблон код проверки многие ребята пишут гвардию служебных классов, как это:

public static class Guard 
{ 
    public static void ThrowIfNull(object argumentValue, string argumentName) 
    { 
     if (argumentValue == null) 
     { 
      throw new ArgumentNullException(argumentName); 
     } 
    } 

    // other validation methods 
} 

(Вы можете добавить другие методы проверки, которые могут быть необходимы для этого класса Guard).

Таким образом, он принимает только одну строку кода для подтверждения параметра:

private static void Foo(object obj) 
    { 
     Guard.ThrowIfNull(obj, "obj"); 
    } 
+0

Ницца! компактный, и он может даже использовать имя оператора :) Спасибо! – SuperJMN

+1

@SuperJMN: Добро пожаловать :) –

+8

Небольшая заметка, вы также можете использовать оператор 'nameof' вместо жесткого кодирования имени аргумента, например. 'Guard.ThrowIfNull (obj, nameof (obj))' –

5

Нулевые ссылки являются один вид проблем вы должны остерегаться. Но они не единственные. Проблема шире, и это сводится к следующему: метод принимает экземпляры определенного типа, но не может обрабатывать все экземпляры.

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

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

В этом случае может оказаться, что подпись метода слишком широка, что указывает на проблему проектирования. Это может привести к редизайну, например. определяя подтип, как правило, производный интерфейс, который ограничивает область метода и устраняет некоторые из защитных предложений. Вы можете найти пример в этой статье: Why do We Need Guard Clauses?

1

Существует пакет nuget под названием Swissknife. Установите Swissknife из галереи nuget. Он предоставляет множество опций, начиная с нулевой проверки аргументов Argument.IsNotNullOrEmpty(args,"args") под номером Swissknife.Diagnostics.Contracts пространства имен с опцией idoim и многих других. Вы можете установить Option<Class_Name> _someVar, а затем проверить, _someVar.IsSome or _SomeVar.IsNone. Это помогает и против классов с нулевым значением. Надеюсь это поможет.

Смежные вопросы