执行using块计数作为对其捕获的IDisposable的引用

本文关键字:IDisposable 引用 using 执行 | 更新日期: 2023-09-27 18:25:09

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

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返回的实例的引用?

执行using块计数作为对其捕获的IDisposable的引用

是。

你不能在没有参考的情况下处理一些东西。

规范规定using (expression) { statement }被编译为:

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

resource是一个参考。

作用域末尾没有对局部变量的隐式引用。一个实现可以(但不是必须)在您最后一次实际引用对象之后对其进行垃圾收集。换句话说,您的第二个代码块是不正确,因为允许在块结束之前收集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

使用块创建一个局部变量,以便在使用块结束时调用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