我可以将C#函数标记为"此函数不会枚举IEnumerable参数"?

时间:2014-05-08 15:47:53

标签: c# resharper ienumerable

同一个枚举的多次枚举对我们来说是一个性能问题,因此我们尝试在代码中踩踏这些警告。但是我们有一个泛型扩展函数用于抛出生成大量这些警告的空参数异常。它的签名如下:

public static void VerifyArgumentIsNotNull<T>(this T value, string valueName) where T : class

所有这一切都是检查null并抛出格式良好且本地化(对于当时正在播放的人类语言)异常。

当在IEnumerable参数上使用此函数时,它会使代码分析警告IEnumerable可能的多次迭代,因为分析器不知道该函数的作用。

我想在这个函数上添加一些标记,&#34;是的,这会将可枚举作为输入,但它不会迭代它,因此不应被调用者视为可能的迭代。 #34;有没有这样的标签?我在互联网上搜索无济于事。

3 个答案:

答案 0 :(得分:18)

是的,你所要求的是非常可能的,但需要一点工作。 ReSharper使用Code Annotations向其分析引擎添加提示,并更好地理解它必须使用的代码。我最近在JetBrains上录制了一个名为ReSharper Secrets的网络研讨会,在那里我详细介绍了注释是什么以及如何使用它们。你应该看看它!

有一个注释属性,[NoEnumeration]完全符合您的要求 - 指定不枚举给定的IEnumerable参数,但它不包含在默认Code Annotation Attributes中,但它是在JetBrains.Annotations.dll程序集中定义。

所以在介绍之后,这就是你需要做的事情:

  1. (如果您还没有),请转到ReSharper选项,然后转到代码检查→代码注释,然后按将默认实施复制到剪贴板按钮
  2. 在名为Annotations.cs(或任何其他名称)的任何(共享)项目中创建文件
  3. 粘贴剪贴板中的代码,完全替换以前Annotations.cs
  4. 中的所有内容
  5. 在文件末尾添加以下定义:
  6. 代码:

    /// <summary>
    /// Indicates that IEnumarable, passed as parameter, is not enumerated.
    /// </summary>
    [AttributeUsage(AttributeTargets.Parameter)]
    public sealed class NoEnumerationAttribute : Attribute
    {
    }
    

    完成此操作后,剩下要做的就是将[NoEnumeration]属性放在value参数上,如下所示:

    public static void VerifyArgumentIsNotNull<T>([NoEnumeration] this T value, string valueName) where T : class
    {
        ....
    }
    

    就是这样!警告将消失!

    <强>加成:

    您可以使用3个其他属性来修饰此方法,使其更有用:[NotNull][ContractAnnotation][InvokerParameterName]。我最近在this issue中描述了他们做了什么(以及一个简短的演示)来获得一个名为LiteGuard的类似API。

    注释很有趣:)

答案 1 :(得分:2)

由于VerifyArgumentIsNotNull是通用的,但没有任何特定的类型,它可以采用一个对象:

public static void VerifyArgumentIsNotNull(this object @object, string argumentName) { ... }

Resharper(9.11。)假设被调用的方法不会将@object转换回IEnumerable,因此没有警告。

注意缺少类约束意味着如果您不小心将值类型传递给VerifyArgumentIsNotNull,编译器可能不会发出警告,但Resharper会警告值类型永远不能为null。

这种方法的另一个优点是可以保存JIT,为每个调用VerifyArgumentIsNotNull的类型创建实例(封闭通用)方法;一个微观优化是可以肯定的,但这是一个罕见的例子,其中通用可能不比老派对象更好。

上面的一个可能的缺点:我已经看到类似的实现,其中VerifyArgumentIsNotNull返回“value”。在这种情况下,需要返回类型为T的值以避免显式转换。 (IMO这种语法很难看。所以对我来说这不是一个缺点。)

另外两篇社论评论:  1.我看到的方法名称:ThrowIfNull更简洁,“Throw”比“Verify”更明确  2.我不再使用方法,因为没有VerifyArgumentIsNotNull上的注释,Resharper必须假设参数仍然可以为null。我发现让R#更简单,当我添加NotNullAttribute时插入一行if + throw。

这种方法不适用于您希望确保使用可枚举方法调用方法的更广泛的情况。在这种情况下,Igal Tabachnik对Annotations的补充很棒。

答案 2 :(得分:0)

假设您在代码分析窗口中使用的是Visual Studio 2013/2012(我在2013年只知道此功能),您应该能够右键单击该消息导航到抑制消息&gt;在源文件在抑制文件中

或者,您可以通过单击“代码分析”窗口中的消息操作下拉列表来实现相同的效果。