簡體   English   中英

using-block中的對象初始值設定項生成代碼分析警告CA2000

[英]Object initializers in using-block generates code analysis warning CA2000

如果我在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。 或者這是代碼分析引擎中的錯誤?

不,有區別。

只有在設置了所有屬性后,對象初始值設定項才會分配給變量。 換句話說,這個:

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

請注意,沒有“Disposing Object initializer”行。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM