简体   繁体   English

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

[英]A using block, with an object initializer block in the constructor

If you call a constructor from a within a using statement the object is automatically disposed is wrapped it with a try/catch block.如果您从using 语句调用构造函数,则会自动处理 object 并用 try/catch 块包装它。 That is an object initializer block in the constructor.那是构造函数中的 object 初始化程序块。

But what becomes with member types that are initialized in the same statement?但是在同一语句中初始化的成员类型会变成什么? eg:例如:

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

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

What happens with MemberThatThrowsAnException when it throws an exception when SomeDisposable is initialized, ie, the code block is executed?当 SomeDisposable 被初始化,即代码块被执行时, MemberThatThrowsAnException抛出异常时会发生什么?

And does it make any difference if we call those members constructors outside the scope of the using block?如果我们在using块的 scope之外调用这些成员构造函数,这有什么区别吗?

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

In some scenarios this can be pretty nice and readable, but I would like to know if thare are any caveats or pitfalls in this way.在某些情况下,这可能非常好且可读,但我想知道这种方式是否有任何警告或陷阱 Or that it is a no-go all the way .或者说一路走不通 Besides that you need to keep the readability in mind.除此之外,您还需要牢记可读性。

Object initializers are in some sense a red herring here... but they're one example of where a problem is avoidable. Object 初始化程序在某种意义上是一个红鲱鱼......但它们是可以避免问题的一个例子。

The object isn't "guarded" by the using statement until the resource acquisition expression has completed normally.在资源获取表达式正常完成之前,object 不会被using语句“保护”。 In other words, your code is like this:换句话说,你的代码是这样的:

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

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

That's more obviously problematic:)这更明显是有问题的:)

Of course the solution is to assign the property inside the using statement:当然解决方案是using语句中分配属性:

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

Now we're only relying on the constructor of SomeDisposable to clean up after itself if it ends up throwing an exception - and that's a more reasonable requirement.现在我们只依赖SomeDisposable的构造函数它最终抛出异常时自行清理——这是一个更合理的要求。

From what I can see, your SomeDisposable class has a property of type TypeThatThrowsAnException, that you're initializing as you instantiate the SomeDisposable - yes?据我所知,您的 SomeDisposable class 具有类型为 TypeThatThrowsAnException 的属性,您在实例化 SomeDisposable 时正在初始化该属性 - 是吗?

using () ie the Dispose pattern is a short-hand that actually emits this: - using () 即 Dispose 模式是一个简写,它实际上发出了这个:-

SomeDisposable ds = null;

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

So if the constructor for your type throws an exception, control will immediately pass to the finally block.因此,如果您的类型的构造函数抛出异常,控制将立即传递给 finally 块。

Find this post on Ayende's blog on the subject.在 Ayende 的博客上找到这篇文章 It's about object initializers in using statements but it seems somehow related to your question.这是关于using语句中的 object 初始化程序,但它似乎与您的问题有关。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM