如果您使用语句中的调用构造函数,则会自动处理该对象,并使用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
在某些情况下,这可能非常好并且可读,但我想知道是否有任何警告或陷阱以这种方式。或者它是一个禁止一直。 除此之外,您还需要牢记可读性。
答案 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
语句中的对象初始值设定项,但它似乎与您的问题有某种关系。