20

コード ベースでコード コントラクトの使用を開始することを考えています。

すべてのルールを有効にし、警告ゼロを目標としてコード分析を既に使用しています。

ただし、使用するContract.Requires(parameter != null)と、コード分析、つまり CA1062 から警告が表示されます。

CA1062 : Microsoft.Design : 外部から見えるメソッド 'Foo' で、パラメーター 'parameter' を使用する前に検証してください。

残念ですが、このルールは便利なので無効にしたくありません。しかし、私はそれのすべての誤った発生を抑制したくありません.

解決策はありますか?

4

2 に答える 2

14

この問題を解決するには、次の手順を実行する必要があります。

  1. コード分​​析で CA1062 を無効にして、コード分析からの警告を取り除きます。現在、コード分析に理解させる方法はありませんContract.Requires
  2. プロジェクトの [Code Contracts] ペインで [Perform Static Contract Checking] を有効にします。
  3. 「暗黙の非 Null 義務」を有効にする
  4. 警告レベルを「こんにちは」に設定します(重要です、それは私が見逃していたものです!)

ステップ 1 は CA 警告を取り除き、ステップ 2 から 4 はコード コントラクトからの少なくとも同等の警告を有効にします。

于 2012-11-09T12:57:24.893 に答える
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は、もちろん、命名スタイルに合ったものに変更できます。

これは、私がこのテクニックを少し改良した元のブログです。彼の研究を公開してくれた Terje Sandstrom に感謝します。

Rico Suter は、デバッガーとインライナーもよりスマートになるように、追加の属性を使用してこれを拡張します。

于 2015-07-26T15:31:57.223 に答える