代码合同+代码分析

时间:2012-11-07 16:22:46

标签: c# .net visual-studio visual-studio-2012 code-contracts

我考虑在我的代码库中开始使用Code Contracts

我已经使用了代码分析,启用了所有规则,目标是零警告。

但是,使用Contract.Requires(parameter != null)时,我会收到代码分析的警告,即CA1062:

  

CA1062:Microsoft.Design:在外部可见方法'Foo'中,在使用之前验证参数'parameter'。

这很不幸,我不想禁用该规则,因为我发现它很有用。但我也不想压制它的每一次错误发生。

有解决方案吗?

2 个答案:

答案 0 :(得分:13)

要解决此问题,需要执行以下步骤:

  1. 在代码分析中禁用CA1062以消除代码分析中的警告。目前无法使代码分析理解Contract.Requires
  2. 在项目的“代码合同”窗格中启用“执行静态合同检查”。
  3. 启用“隐含的非空义务”
  4. 将警告级别设置为“hi”(重要的是,这是我错过的!)
  5. 步骤1取消CA警告,步骤2到4启用代码合同中的警告,该警告至少相当于。

答案 1 :(得分:4)

从框架的版本4.5.2(甚至可能是4.5)开始,可以告诉代码分析有关代码合同强制执行的合同。首先创建以下扩展方法和标记属性

  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 当然可以更改为适合您命名方式的任何内容。

Here is the original blog告诉了我这种技术,我稍微提炼了一下;非常感谢Terje Sandstrom发表他的研究成果。

Rico Suter通过使用其他属性扩展了此here,以便调试器和内联器也更智能: