Почему я получаю анализ кода CA1062 для выходного параметра в этом коде?

У меня очень простой код (упрощенный по сравнению с исходным кодом - поэтому я знаю, что это не очень умный код), который при компиляции в Visual Studio 2010 с анализом кода выдает предупреждение 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?

ОБНОВЛЕНИЕ

Я решил открыть отчет об ошибке в Microsoft Connect.


person brickner    schedule 18.05.2010    source источник
comment
Интересно, где-то проблема ...   -  person Hamish Grubijan    schedule 19.05.2010
comment
Опять без репродукции. Нечего подтверждать. Вы разместили другие предупреждения анализа кода, которые не воспроизводятся. Если вы внесли какие-либо изменения в конфигурацию, обязательно задокументируйте их.   -  person Hans Passant    schedule 19.05.2010
comment
@Hans Passant, вы уверены, что используете все правила анализа кода Microsoft в Visual Studio 2010?   -  person brickner    schedule 19.05.2010
comment
Я тоже не вижу, чтобы кто-то это повторял.   -  person Hans Passant    schedule 19.05.2010
comment
@Hans Passant, я могу его без проблем перепрограммировать. У меня есть проект в решении, которое, без сомнения, воспроизводит каждую компиляцию. Я не уверен, что все не могут повторить это, вы единственный, кто написал, что он пытался и потерпел неудачу.   -  person brickner    schedule 19.05.2010
comment
Я воспроизвел это в Visual Studio 2010 Premium. Я просто вставил класс, как указано в вопросе, включил Все правила Microsot в настройках и проанализировал проект.   -  person Daniel Renshaw    schedule 20.05.2010


Ответы (2)


Я воспроизвел это в Visual Studio 2010 Premium с точно таким же кодом и с включенными Microsoft All Rules в настройках анализа.

Похоже, это ошибка (см. Внизу здесь: http://msdn.microsoft.com/en-us/library/ms182182.aspx). Выражается жалоба на то, что вы не проверяете, что x не является нулевым перед его использованием, но он находится в параметре out, поэтому нет входного значения для проверки!

person Daniel Renshaw    schedule 18.05.2010

Проще показать, чем описать:

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;
    }
person Diadistis    schedule 18.05.2010
comment
хорошо, но почему правильный путь правильный? Или вы говорите, что это правильно, потому что при анализе кода нет предупреждения? - person Gabriel Magana; 19.05.2010
comment
То, что вы показали, безусловно, является важным моментом (если x может быть доступен из нескольких потоков), но я не думаю, что это то, что CA1062 призван подчеркнуть. Если вы читаете документацию здесь: msdn.microsoft.com/en-us/library /ms182182.aspx, очевидно, что это предназначено для ref параметров и является стандартной проверкой, не является ли значение null перед использованием этого правила. Ошибка в том, что она применяется к out параметрам. Действительно ли это предотвращает выдачу предупреждения CA1062? - person Daniel Renshaw; 19.05.2010
comment
@gmagana: правильный способ является потокобезопасным и не генерирует исключение NullReferenceException ни на что. - person Diadistis; 19.05.2010
comment
@Daniel: Все ссылочные аргументы ... out тоже считаются ссылочными аргументами. - person Diadistis; 19.05.2010
comment
Да, ок. Но out - это ссылочный аргумент только для вывода, а ref - это ссылочный аргумент ввода / вывода. Нет необходимости выполнять проверку ввода (о чем и идет речь в CA1062) для параметра, предназначенного только для вывода. - person Daniel Renshaw; 19.05.2010
comment
Единственная разница между out и ref заключается в том, что параметру нужно присвоить значение, это похоже на контракт. Когда вы обращаетесь к x с помощью индексатора, вы фактически читаете его. - person Diadistis; 19.05.2010
comment
Но получить к нему доступ с помощью индексатора невозможно, пока после вы не присвоите ему значение внутри метода. Если вы попытаетесь, он не скомпилируется. Невозможно передать информацию в метод с помощью параметра out. - person Daniel Renshaw; 20.05.2010