Инициализаторы объектов в блоке using генерируют предупреждение анализа кода CA2000 - PullRequest
18 голосов
/ 18 августа 2010

Если я использую инициализаторы объекта в блоке using, я получаю предупреждение Code Analysis о неправильной утилизации объекта:

CA2000: Microsoft.Reliability: В методе 'ReCaptcha.CreateReCaptcha (это HtmlHelper, string, string)', объект' <> g__initLocal0 'расположен не по всем путям исключений.Вызовите System.IDisposable.Dispose для объекта '<> g__initLocal0' до того, как все ссылки на него выйдут из области видимости.

Вот код:


    using (var control = new ReCaptchaControl()
    {
        ID = id,
        Theme = theme,
        SkipRecaptcha = false
    })
    {
        // Do something here
    }

Если я не использую инициализаторы объекта, Анализ кода счастлив:


    using (var control = new ReCaptchaControl())
    {
        control.ID = id;
        control.Theme = theme;
        control.SkipRecaptcha = false; 

        // Do something here
    }

В чем разница между этими двумя кодовыми блоками?Я думал, что они приведут к тому же IL.Или это ошибка в механизме анализа кода?

1 Ответ

32 голосов
/ 18 августа 2010

Нет, разница есть.

Инициализатор объекта присваивает переменной только после все свойства. Другими словами, это:

Foo x = new Foo { Bar = "Baz" };

эквивалентно:

Foo tmp = new Foo();
tmp.Bar = "Baz";
Foo x = tmp;

Это означает, что если в вашем случае один из установщиков свойств вызовет исключение, объект не будет удален.

РЕДАКТИРОВАТЬ: Как я и думал ... попробуйте это:

using System;

public class ThrowingDisposable : IDisposable
{
    public string Name { get; set; }

    public string Bang { set { throw new Exception(); } }

    public ThrowingDisposable()
    {
        Console.WriteLine("Creating");
    }

    public void Dispose()
    {
        Console.WriteLine("Disposing {0}", Name);
    }
}

class Test
{
    static void Main()
    {
        PropertiesInUsingBlock();
        WithObjectInitializer();
    }

    static void PropertiesInUsingBlock()
    {
        try
        {
            using (var x = new ThrowingDisposable())
            {
                x.Name = "In using block";
                x.Bang = "Ouch";
            }
        }
        catch (Exception)
        {
            Console.WriteLine("Caught exception");
        }
    }

    static void WithObjectInitializer()
    {
        try
        {
            using (var x = new ThrowingDisposable
            {
                Name = "Object initializer",
                Bang = "Ouch"
            })
            {
                // Nothing
            }
        }
        catch (Exception)
        {
            Console.WriteLine("Caught exception");
        }
    }
}

Выход:

Creating
Disposing In using block
Caught exception
Creating
Caught exception

Обратите внимание, что нет строки «Утилизация инициализатора объекта».

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...