如何告诉R#一个函数检查一个变量是否为空

8
在我们的代码库中,我们有一系列自定义错误检查函数(例如在这里列出的函数),可以更简洁地检查参数。例如,要检查一个参数是否为 null,我使用以下代码:
Throw.IfNull(theArgument, "theArgument");

这种方法的一个缺点是,R#会在将来使用该值时发出“可能的NullReferenceException”警告,因为它不足够聪明,无法检测到这是空检查(或者至少是如果theArgument为空将失败的东西)。有没有办法表明这种方法检查参数是否为空?例如,当我尝试在这样的值上运行静态扩展Select()时,R#会警告我“可能将null赋值给标记为NotNull属性的实体”,但我找不到任何关于这种属性的文档,也没有在Enumerable.Select()的参考源中看到它。
1个回答

16
您所提出的问题可以通过应用ReSharper注释来解决!这些属性为ReSharper的分析提供了额外的提示,使您能够将ReSharper的“好处”添加到自己的方法和类中。我最近与JetBrains一起录制了一个名为ReSharper Secrets的网络研讨会,在其中讲解和演示了注释,欢迎您观看!
至于您的问题,有3个注释属性可以应用来解决您的问题(并添加更多酷炫的功能)。
假设IfNull的定义是这样的:
public static class Throw
{
    public static void IfNull<T>(T parameter, string parameterName) where T : class
    {
        if (parameter == null) 
            throw ArgumentNullException(string.Format("Parameter {0} is null", parameterName));
    }
}

你可以使用3个ReSharper属性来装饰它,ContractAnnotationNotNullInvokerParameterName,就像这样:
[ContractAnnotation("parameter: null => halt")]
public static void IfNull<T>([NotNull] T parameter,
                             [InvokerParameterName] string parameterName) 
    where T : class
{
    ...
}

以下是这些属性的作用:

第一个属性[ContractAnnotation]告诉ReSharper,如果parameter在启发式上为null,则该方法会停止程序执行,即在运行时抛出异常。这就是防止“可能的NullReferenceException”警告的方法。定义Contract注释所使用的语言在这里解释。

第二个属性[NotNull]告诉ReSharper,parameter不能在启发式上为null。这会导致“可能将null赋值给标记为[NotNull]属性的实体”警告。

第三个属性[InvokerParameterName]告诉ReSharper,parameterName参数是调用(调用)方法中一个参数的名称,因此它将提供代码完成,列出所有调用方法的参数。如果名称不是参数,例如局部变量名称,则ReSharper会给出警告。

这是一个展示这些属性运作的短视频(应用于另一组API,但思路完全相同):http://screencast.com/t/NhGVaUr7GO3b

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接