如果从using语句中调用构造函数,则会自动处理该对象,并使用try/catch块对其进行包装.这是构造函数中的对象初始化程序块.
但是在同一语句中初始化的成员类型会变成什么?例如:
class TypeThatThrowsAnException
{
public TypeThatThrowsAnException()
{
throw new Exception();
}
}
using (SomeDisposable ds = new SomeDisposable() {
MemberThatThrowsAnException m = new TypeThatThrowsAnException()
})
{
// inside using statement
ds.doSomething();
}
Run Code Online (Sandbox Code Playgroud)
以会发生什么MemberThatThrowsAnException时,它抛出时SomeDisposable被初始化,即,被执行的代码块中的例外呢?
如果我们将那些成员构造函数调用到块的范围之外,它会有什么不同using吗?
class TypeThatThrowsAnException
{
public TypeThatThrowsAnException()
{
throw new Exception();
}
}
class SomeClass
{
public static TypeThatThrowsAnException StaticMember
{
get
{
return new TypeThatThrowsAnException();
}
}
}
using (SomeDisposable ds = new SomeDisposable() {
MemberThatThrowsAnException = SomeClass.StaticMember
})
{
// inside using statement
ds.doSomething();
}
Run Code Online (Sandbox Code Playgroud)
在某些情况下,这可能是非常好的和可读的,但我想知道是否有这样的任何警告或陷阱.或者说这是一直禁止的.除此之外,您还需要牢记可读性.
对象初始化是在一些感觉这里的红鲱鱼......但他们是哪里的问题是可以避免的一个例子。
using在资源获取表达式正常完成之前,该对象不会被语句“保护” 。换句话说,你的代码是这样的:
SomeDisposable tmp = new SomeDisposable();
tmp.MemberThatThrowsAnException = new TypeThatThrowsAnException();
using (SomeDisposable ds = tmp)
{
// Stuff
}
Run Code Online (Sandbox Code Playgroud)
这显然有问题:)
当然,解决办法是财产分配中的using语句:
using (SomeDisposable ds = new SomeDisposable())
{
MemberThatThrowsAnException = new TypeThatThrowsAnException();
// Stuff
}
Run Code Online (Sandbox Code Playgroud)
现在,如果最终抛出异常,我们只依赖于的构造函数SomeDisposable在其自身之后进行清理——这是一个更合理的要求。