Подтвердить что ты не робот

Кодовые контракты + анализ кода

Я думаю о начале использования Кодовых контрактов в моей базе кода.

Я уже использую Code Analysis со всеми включенными правилами и целью нулевых предупреждений.

Однако при использовании Contract.Requires(parameter != null) я получаю предупреждение от Code Analysis, а именно CA1062:

CA1062: Microsoft.Design: во внешнем видимом методе "Foo" перед использованием его следует проверить параметр "параметр".

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

Есть ли решение?

4b9b3361

Ответ 1

Начиная с версии 4.5.2 структуры (возможно, даже 4.5), можно рассказать Code Analysis о заключении контрактов, заключенных в Code Contracts. Сначала создайте следующий метод расширения и атрибут маркера

  using System;
  using System.Diagnostics;
  using System.Diagnostics.CodeAnalysis;
  using System.Diagnostics.Contracts;

  /// <summary>Extension methods to enhance Code Contracts and integration with Code Analysis.</summary>
  public static class ContractExtensions {
#if RUNTIME_NULL_CHECKS
    /// <summary>Throws <c>ArgumentNullException{name}</c> if <c>value</c> is null.</summary>
    /// <param name="value">Value to be tested.</param>
    /// <param name="name">Name of the parameter being tested, for use in the exception thrown.</param>
    [ContractArgumentValidator]  // Requires Assemble Mode = Custom Parameter Validation
    public static void ContractedNotNull<T>([ValidatedNotNull]this T value, string name) where T : class {
      if (value == null) throw new ArgumentNullException(name);
      Contract.EndContractBlock();
    }
#else
    /// <summary>Throws <c>ContractException{name}</c> if <c>value</c> is null.</summary>
    /// <param name="value">Value to be tested.</param>
    /// <param name="name">Name of the parameter being tested, for use in the exception thrown.</param>
    [SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "value")]
    [SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "name")]
    [ContractAbbreviator] // Requires Assemble Mode = Standard Contract Requires
    public static void ContractedNotNull<T>([ValidatedNotNull]this T value, string name) where T : class {
      Contract.Requires(value != null,name);
    }
#endif
  }

/// <summary>Decorator for an incoming parameter that is contractually enforced as NotNull.</summary>
[AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false)]
public sealed class ValidatedNotNullAttribute : global::System.Attribute {}

и теперь конвертируйте ваши нулевые тесты в следующий формат:

/// <summary>IForEachable2{TItem} implementation</summary>
public   void  ForEach(FastIteratorFunctor<TItem> functor) {
  functor.ContractedNotNull("functor"); // for Code Analysis

  TItem[] array = _array;
  for (int i = 0; i < array.Length; i++)    functor.Invoke(array[i]);
}

Имя метода ContractedNotNull и переключатель компиляции RUNTIME_NULL_CHECKS можно, конечно, изменить на все, что соответствует вашему стилю именования.

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

Rico Suter расширяет эту здесь, используя дополнительные атрибуты, чтобы отладчик и inliner были более умными:

Ответ 2

Для решения этой проблемы необходимо выполнить следующие шаги:

  • Отключите CA1062 в анализе кода, чтобы избавиться от предупреждения из анализа кода. В настоящее время нет способа сделать анализ кода понятным Contract.Requires.
  • Включить "Выполнение статической проверки контрактов" в панели "Контракты кода" проекта.
  • Включить "Неявные непустые обязательства"
  • Установите уровень предупреждения на "привет" (важно, это было то, что мне не хватало!)

Шаг 1 избавляется от предупреждения CA, шаги с 2 по 4 разрешают предупреждение из кодовых контрактов, которые по меньшей мере эквивалентны.