一个using块,在构造函数中有一个对象初始化块

时间:2011-07-04 06:37:30

标签: c#

如果您使用语句中的调用构造函数,则会自动处理该对象,并使用try / catch块对其进行包装。这是构造函数中的对象初始化程序块。

但是在同一语句中初始化的成员类型会变成什么? e.g:

  class TypeThatThrowsAnException 
  {
       public TypeThatThrowsAnException() 
       {
           throw new Exception();
       }
  }

  using (SomeDisposable ds = new SomeDisposable() {
       MemberThatThrowsAnException m = new TypeThatThrowsAnException()
  })
  {
       // inside using statement
       ds.doSomething();
  }

MemberThatThrowsAnException初始化SomeDisposable时抛出异常,即执行代码块会发生什么?

如果我们将那些成员构造函数在<{1}}块的范围之外称为,会有什么不同吗?

using

在某些情况下,这可能非常好并且可读,但我想知道是否有任何警告或陷阱以这种方式。或者它是一个禁止一直除此之外,您还需要牢记可读性。

3 个答案:

答案 0 :(得分:4)

对象初始化器在某些意义上是一个红色的鲱鱼......但它们是问题可以避免的一个例子。

在资源获取表达式正常完成之前,using语句不会“保护”该对象。换句话说,您的代码是这样的:

SomeDisposable tmp = new SomeDisposable();
tmp.MemberThatThrowsAnException = new TypeThatThrowsAnException();

using (SomeDisposable ds = tmp)
{
    // Stuff
}

这显然有问题:)

当然解决方案是在<{1}}语句中分配属性

using

现在我们只依靠using (SomeDisposable ds = new SomeDisposable()) { MemberThatThrowsAnException = new TypeThatThrowsAnException(); // Stuff } 的构造函数来清理它自己如果它最终会抛出异常 - 这是一个更合理的要求。

答案 1 :(得分:1)

从我所看到的,你的SomeDisposable类有一个TypeThatThrowsAnException类型的属性,你在实例化SomeDisposable时正在初始化 - 是吗?

使用(),即Dispose模式实际上是这样的简写: -

SomeDisposable ds = null;

try
{
    ds = new SomeDisposable();
}
finally
{
    if (ds != null)
        ds.Dispose();
}

因此,如果您的类型的构造函数抛出异常,控件将立即传递给finally块。

答案 2 :(得分:1)

在Ayende的博客上查找关于此主题的this post。它是关于using语句中的对象初始值设定项,但它似乎与您的问题有某种关系。