C# 一个using块,构造函数中有一个对象初始值设定项块

C# 一个using块,构造函数中有一个对象初始值设定项块,c#,C#,如果从using语句中调用构造函数,对象将自动释放,并用try/catch块将其包装。这是构造函数中的对象初始值设定项块 但是在同一语句中初始化的成员类型会怎么样呢?e、 g: class TypeThatThrowsAnException { public TypeThatThrowsAnException() { throw new Exception(); } } using (SomeDisposabl

如果using语句中调用构造函数,对象将自动释放,并用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();
  }
当初始化某个一次性文件(即执行代码块)时,通过异常的
成员抛出异常时,会发生什么情况

如果我们使用
块在范围之外调用这些成员构造函数,会有什么区别吗

  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();
  }

在某些情况下,这可能是非常好和可读的,但我想知道是否有这样的警告或陷阱。或者说这是一个“一路禁止”
。除此之外,您还需要记住可读性。

对象初始值设定项在某种意义上是一个麻烦。。。但它们是一个可以避免问题的例子

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

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

using (SomeDisposable ds = tmp)
{
    // Stuff
}
更明显的问题是:)

当然,解决方案是使用语句在
中指定属性:

using (SomeDisposable ds = new SomeDisposable())
{
    MemberThatThrowsAnException = new TypeThatThrowsAnException();
    // Stuff
}

现在,我们只依赖于
SomeDisposable
的构造函数来清理它自己,如果它最终抛出异常,这是一个更合理的要求。

从我所看到的,SomeDisposable类有一个类型为TypeThrowsanException的属性,当您实例化SomeDisposable时正在初始化-是吗

使用()-

SomeDisposable ds = null;

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

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

在Ayende的博客上找到该主题。这是关于
中使用
语句的对象初始值设定项,但它似乎与您的问题有关。

您的意思是使用一个using语句,然后使用一个单独的块吗?你的代码目前还不是很清楚。@Jon:我相信OP的意思是有一个using块,在constructor语句中有一个object initializer块。我也被这两对花括号弄糊涂了:P@Tomas当前位置是的,我以前没有把它计算好。我现在已经:)我现在已经知道可读性是这里的主要问题,然而……)@Caspar:看起来您正试图在对象初始值设定项中声明一个新变量(
m
),这并没有帮助。当前发布的代码无法编译。不,这不是正确的翻译-因为在try块中有
SomeDisposable
构造函数调用。不是。在试块之前。请参见C#4规范第8.13节。注意,谢谢Jon。顺便说一句,如果有人想要的话,这里就是——也许我错了,但是using语句是通过try/finally实现的,所以即使在构造时间(类型初始值设定项)之后抛出了一些异常,IDisposable.Dispose方法也将始终被调用。我错了吗?@Matias:它只有在资源获取成功后才进入try块,所以在这里没有帮助。请注意,我们谈论的是对象初始值设定项,而不是类型初始值设定项-非常不同的事情。我明白了,顺便说一句,这是一个lapsus:我谈论的是对象初始值设定项。对于第一个片段-如何处理
tmp
?是否通过引用
ds
来处理它?
ds
也需要处理吗?@anatol:除非
SomeDisposable
是一个结构,
tmp
ds
指的是同一个对象。不管该对象是如何处理的(即通过哪个变量),重要的是它是如何处理的。