我考虑开始在我的代码库中使用代码契约。
我已经在启用所有规则并以零警告为目标的情况下使用代码分析。
但是,在使用时,Contract.Requires(parameter != null)
我收到了来自代码分析的警告,即 CA1062:
CA1062:Microsoft.Design:在外部可见的方法“Foo”中,在使用之前验证参数“parameter”。
不幸的是,我不想禁用该规则,因为我发现它很有用。但我也不想压制它的每一次错误发生。
有解决办法吗?
我考虑开始在我的代码库中使用代码契约。
我已经在启用所有规则并以零警告为目标的情况下使用代码分析。
但是,在使用时,Contract.Requires(parameter != null)
我收到了来自代码分析的警告,即 CA1062:
CA1062:Microsoft.Design:在外部可见的方法“Foo”中,在使用之前验证参数“parameter”。
不幸的是,我不想禁用该规则,因为我发现它很有用。但我也不想压制它的每一次错误发生。
有解决办法吗?
为了解决这个问题,需要执行以下步骤:
Contract.Requires
。步骤 1 消除了 CA 警告,步骤 2 到 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 在这里通过使用附加属性对此进行了扩展,以便调试器和内联器也更智能: