首页 > 解决方案 > 我可以在 using 语句中安全地使用对象初始化器吗?

问题描述

我想知道在 using 语句中使用对象初始化器是否会以某种方式阻止正确处理其中声明的资源,例如

using (Disposable resource = new Disposable() { Property = property })
{
   // ...
}

我读过对象初始化器只不过是同步糖,编译器将其转换为类似于以下代码的内容:

MyClass tmp = new MyClass(); 
tmp.Property1 = 1;
tmp.Property2 = 2;
actualObjectYouWantToInitialize = tmp;

即使我可能看起来像一个困惑的无知,我也想要求澄清。初始化对象(据我所知)是指向另一个对象的指针(据我所知,这也是一个指针)这一事实是否会干扰using语句对资源的处理?

标签: c#using-statementobject-initializers

解决方案


主要(唯一?)危险是,如果设置Property失败(即抛出异常),则resource 不会是Disposed

using (Disposable resource = new Disposable() { Property = property })
{
   // ...
}

通常using,块中的异常是可以的——因为 .usingtry .. finally.

这里的问题是,当你有效地Property = property执行时,你还没有“在”块内。这与构造函数抛出异常时发生的情况本质上没有什么不同。using

finally块将尝试的事情Disposeresource- 但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");
        }
    }
}

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


推荐阅读