假设我已经定义了以下方法。
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
返回的实例的引用?
答案 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