使用块是否保证在块结束之前不会丢弃对象?

时间:2013-07-07 20:02:35

标签: c# idisposable using

我知道using块确保被“使用”的IDisposable对象将被放置在块的末尾 - 但保证该对象将在此之前不被处置?

换句话说,如果我有:

using (new DisposableObject()) {
  // blah blah
}

我可以确定DisposableObject在块结束之前不会被释放,或者垃圾收集器是否检测到我在块内没有处理它,并立即处理它?<​​/ p>

3 个答案:

答案 0 :(得分:6)

不,不。没有什么可以阻止你做的事情:

using(var myObject = new DisposableObject())
{
    myObject.Dispose();
}

在这种情况下究竟会发生什么取决于DisposableObject的语义。它可能会抛出异常,或者可能非常满意Dispose被调用两次。

应该注意的是,对象处理和垃圾收集是完全不同的概念。仅仅因为一个对象被处理并不意味着它将被垃圾收集,并且仅仅因为一个对象被垃圾收集并不意味着它将被处理掉。

一旦对对象的所有引用都被破坏或无法访问,对象就可能被垃圾收集。当代码在using - 块内运行时,这不会发生,因为块本身具有对该对象的引用。

答案 1 :(得分:4)

您的对象只会被丢弃一次,并且在使用块结束之前不会进行GC。

规范保证当你有using (expression) statement并且表达式类型是可以为空的类型(称之为ResourceType)时,它会扩展为:

{
   ResourceType resource = expression;
   try {
      statement;
   }
   finally {
      if (resource != null) ((IDisposable)resource).Dispose();
   }
}

Dispose将在块的末尾调用一次,并且有一个本地生成的,用于保持对一次性对象的引用。本地阻止对象在使用块结束之前进行GC。

答案 2 :(得分:2)

我认为您更愿意了解垃圾收集而不是处理。

垃圾收集器不会收集using块内的对象。即使你专门调用Dispose方法,仍然有一个活动的引用,所以它不会被收集。

using块生成的代码以检查对象是否可以处置结束,以便在using块期间使用将使对象保持活动状态。