使用块计数作为它捕获的IDisposable的引用吗?

时间:2013-07-26 16:44:39

标签: c# .net garbage-collection

假设我已经定义了以下方法。

static object F()
{
    return new object();
}

如果我编写如下代码,则在范围结束之前不能对返回的object进行垃圾回收。

{
    object x = F();
    // cannot yet garbage collect the object
    // returned by F (referenced as variable x)
}
// can now garbage collect the object
// returned by F (referenced as variable x)

如果我编写如下代码,则object返回后可立即对返回的F进行垃圾回收。

{
    F();
    // can now garbage collect the object
    // returned by F
}

但现在假设我将F的定义更改为以下内容。

static IDisposable F()
{
    return new SomeDisposableObject();
}

如果我编写如下代码,则返回的对象不能被垃圾收集,并且在using块结束之前不会被丢弃。

using (IDisposable x = F())
{
} // immediately x.Dispose()
// can now garbage collect the object
// returned by F

如果我编写如下代码,那么行为是什么?对C#语言规范的引用是有利的。

using (F())
{
}

using块是否计为F返回的实例的引用?

2 个答案:

答案 0 :(得分:6)

如果没有参考,你就无法处置。

编译using (expression) { statement }的规范states

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

resource是参考。

答案 1 :(得分:1)

在作用域末尾没有对局部变量的隐式引用。在上次实际引用对象之后,实现可能(但不是必需)进行垃圾收集。换句话说,您的第二个代码块不正确,因为在块结束之前允许收集x

{
    object x = F();
    // <-- x IS ALLOWED to be collected here
    Thread.Sleep(5000);
    // <-- The object x ref'd IS ALLOWED to be collected here, if it wasn't earlier
}
// <-- The object x ref'd IS ALLOWED to be collected here, if it wasn't earlier

using块创建一个局部变量,以便在using块的末尾调用Dispose。即使您没有明确命名变量,引用也将一直存在,直到块结束。

using (F())
{
    // The instance returned by F IS NOT allowed to be collected here
    Thread.Sleep(5000);
    // The instance returned by F IS NOT allowed to be collected here
}
// The instance returned by F IS allowed to be collected here