using-block中的对象初始值设定项生成代码分析警告CA2000

Ter*_*ero 18 .net c# visual-studio-2010

如果我在using-block中使用对象初始值设定项,我会收到有关未正确处理对象的代码分析警告:

CA2000:Microsoft.Reliability:在方法'ReCaptcha.CreateReCaptcha(this HtmlHelper,string,string)'中,对象'<> g__initLocal0'未沿所有异常路径放置.在对对象'<> g__initLocal0'的所有引用都超出范围之前,调用System.IDisposable.Dispose.

这是代码:


    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.或者这是代码分析引擎中的错误?

Jon*_*eet 32

不,有区别.

只有在设置了所有属性后,对象初始值设定项才会分配给变量.换句话说,这个:

Foo x = new Foo { Bar = "Baz" };
Run Code Online (Sandbox Code Playgroud)

相当于:

Foo tmp = new Foo();
tmp.Bar = "Baz";
Foo x = tmp;
Run Code Online (Sandbox Code Playgroud)

这意味着如果其中一个属性设置器在您的情况下引发了异常,则不会丢弃该对象.

编辑:我想...试试这个:

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");
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

输出:

Creating
Disposing In using block
Caught exception
Creating
Caught exception
Run Code Online (Sandbox Code Playgroud)

请注意,没有"Disposing Object initializer"行.

  • @Gishu:如果你担心财产制定者可能会抛出异常,是的. (2认同)