为什么我在这段代码中的一个输出参数上得到了Code Analysis CA1062?

11

我有一段非常简单的代码(从原始代码中简化而来,所以我知道这不是一段非常聪明的代码),当我在Visual Studio 2010中编译并使用Code Analysis时,会给出一个警告CA1062:验证公共方法的参数。

public class Foo
{
    protected static void Bar(out int[] x)
    {
        x = new int[1];
        for (int i = 0; i != 1; ++i)
            x[i] = 1;
    }
}

我收到的警告:

CA1062:Microsoft.Design:在外部可见的方法“Foo.Bar(out int [])”中,验证本地变量“(* x)”,该变量在使用之前从参数“x”重新分配。

我不明白为什么会收到这个警告,如何在不抑制它的情况下解决它?new可以返回null吗?这是Visual Studio 2010的bug吗?

更新

我决定在Microsoft Connect上报告错误


我想知道问题是否出在其他地方... - Hamish Grubijan
再次无法重现。没有什么需要验证的了。您已经发布了其他代码分析警告,但是无法重现。如果您进行了任何配置更改,请务必记录它们。 - Hans Passant
@Hans Passant,您确定在Visual Studio 2010中运行了所有Microsoft代码分析规则吗? - brickner
我也没有看到其他人在复现这个问题。 - Hans Passant
@Hans Passant,我可以轻松地重现它。我有一个项目在解决方案中,每次编译都可以毫无疑问地重现它。我不确定每个人都不能重现它,你是唯一一个写过尝试但失败的人。 - brickner
2
我已经在Visual Studio 2010 Premium中复现了这个问题。我只是按照问题中给出的类进行粘贴,打开设置中的“Microsoft All Rules”并分析了项目。 - Daniel Renshaw
2个回答

阿里云服务器只需要99元/年,新老用户同享,点击查看详情
9
我已经在Visual Studio 2010 Premium中复制了给定的代码,并启用了“Microsoft All Rules”分析设置,结果出现了相同的问题。根据此处底部的信息(http://msdn.microsoft.com/en-us/library/ms182182.aspx),看起来这是一个bug。它抱怨您在使用之前没有检查x是否为null,但它是一个out参数,因此没有输入值可供检查!

8

展示比描述更容易:

public class Program
{
    protected static int[] testIntArray;

    protected static void Bar(out int[] x)
    {
        x = new int[100];
        for (int i = 0; i != 100; ++i)
        {
            Thread.Sleep(5);
            x[i] = 1; // NullReferenceException
        }
    }

    protected static void Work()
    {
        Bar(out testIntArray);
    }

    static void Main(string[] args)
    {
        var t1 = new Thread(Work);
        t1.Start();

        while (t1.ThreadState == ThreadState.Running)
        {
            testIntArray = null;
        }
    }
}

正确的方式是:

    protected static void Bar(out int[] x)
    {
        var y = new int[100];

        for (int i = 0; i != 100; ++i)
        {
            Thread.Sleep(5);
            y[i] = 1;
        }

        x = y;
    }

你所展示的肯定是个重要的观点(如果 x 可能被多个线程访问),但我认为这不是 CA1062 的宗旨所在。如果您阅读此处的文档:http://msdn.microsoft.com/en-us/library/ms182182.aspx,显然这是针对 ref 参数而设计的,只是一条标准的“在使用之前检查其是否为空”的规则。将其应用于 out 参数是一个错误。这实际上是否可以防止 CA1062 警告? - Daniel Renshaw
1
@gmagana:正确的方式是线程安全的,无论如何都不会抛出NullReferenceException。 - Diadistis
@Daniel:“所有引用参数...”,out 也被视为引用参数。 - Diadistis
是的,没错。但是 out 是一个只输出的引用参数,而 ref 是输入/输出的引用参数。在仅输出的参数上执行输入验证(这就是 CA1062 的作用)是没有必要的。 - Daniel Renshaw
但是在方法内部赋值之前,无法使用索引器访问它。如果尝试这样做,编译将失败。没有办法通过“out”参数将信息传递到方法中。 - Daniel Renshaw
显示剩余2条评论

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