Can I safely use object initializers inside using statements?

Sta*_*oyd 4 c# using-statement object-initializers

I'm wondering if the use of object initializers inside using statements somehow prevents the correct disposal of the resource declared inside them, e.g.

using (Disposable resource = new Disposable() { Property = property })
{
   // ...
}
Run Code Online (Sandbox Code Playgroud)

I've read that object initializers are nothing but synctatic sugar, which the compiler translates to something similar to the following code:

MyClass tmp = new MyClass(); 
tmp.Property1 = 1;
tmp.Property2 = 2;
actualObjectYouWantToInitialize = tmp;
Run Code Online (Sandbox Code Playgroud)

Even if I may appear as a confused ignorant, I'd like to ask for clarifications. Does the fact that the initialized object is (as far as I understand) a pointer to another object (which is also a pointer, as far as I know), interfere with the disposal of the resource done by a using statement?

mjw*_*lls 6

主要的(唯一的)危险是,如果设置Property失败(即引发异常),则resource 不会被设置为Disposed

using (Disposable resource = new Disposable() { Property = property })
{
   // ...
}
Run Code Online (Sandbox Code Playgroud)

通常using块内的例外是很好的-因为using语法是语法糖try .. finally

这里的问题是,在有效Property = property执行时,您还没有“深入”该块。这与构造函数引发异常的情况本质上没有什么不同。using

所有属性都设置好之后,设置该finally块将要尝试执行的Dispose操作resource(但resource从未设置过)resource(如您的actualObjectYouWantToInitialize示例所示) 。

https://dotnetfiddle.net/vHeu2F演示了在实践中可能如何发生。请注意Dispose,即使有两个using块,也只记录一次。

using System;

namespace Bob
{
    public class Disposable : IDisposable
    {
        private int _property;

        public int Property { get => _property; set => throw new Exception(); }

        public void Dispose()
        {
            Console.WriteLine("Disposed");
        }
    }

    public class Program
    {
        public static void Main()
        {
            Console.WriteLine("1");
            using (var resource = new Disposable())
            {
                Console.WriteLine("2");
            }
            Console.WriteLine("3");


            using (var resource = new Disposable() { Property = 1 })
            {
                Console.WriteLine("4");

            }
            Console.WriteLine("5");
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

CA2000可能有助于检测此问题。

  • @StackLloyd通过使用对象初始化器语法,首先创建对象,然后设置属性。因此,创建了实例(需要处理),但是没有将其分配(如您所说)分配给将在finally块中处理的变量。所以你有泄漏。 (3认同)