使用和垃圾回收

7

您好,我来澄清一下,如果我有以下内容:

using (Object1) {
create Object2
}
// bookmark1

Object2会和Object1一起在bookmark1被销毁吗? Object2是StringReader,Object1是MemoryStream。

顺便问一下 - 当我们到达bookmark1时,Object1会立即被销毁,还是只是没有引用并等待垃圾回收出现? - cwap
请问C#中的using块是什么,为什么要使用它? - plinth
它将会是“超出范围”(与未引用相同),所以只需等待垃圾回收器出现并稍后清理它。 - Orion Edwards
4个回答

21

块结束时,两个对象都不会被销毁

Object1将被处置(disposed),这是一个不同的概念;Object2则不会有任何变化。

两个对象都将被收集,并且可能在稍后进行终结。垃圾回收是不确定性的 - 您无法依赖于它何时发生。

有关详细信息,请参见MSDN上的IDisposable


3
一个 using 块实际上只是以下结构的语法糖:
try
{
    Brush b = new SolidBrush(Color.Red);
}
finally
{
    b.Dispose();
}

所以,除非发生应用程序无法控制的情况,否则'b'将在try块结束时被处理掉。

接近了,但不完全正确。在你的代码中,b仍然在作用域内,因此它不能被回收,当块结束时你还不能重新使用这个名称。 - Joel Coehoorn
是的,我刚刚修好了。谢谢。 - Ed S.

1
在你的示例中,在块的末尾(bookmark1)只有对象1将被处理。对于文件流而言,这意味着流将被关闭并释放句柄,但实际的字符串对象仍然在内存中(准备由GC清理)。在你的情况下,Object2不会被处理,因此它使用的句柄仍将保持打开状态。最终,GC将收集它,并调用其终结器,此时它将被正确释放。
如果你想要两个对象都被“清理”正确地处理,它们都需要被处理,可以通过将它们包装在using语句中或手动调用Dispose来实现。
还有另一种可能更简洁的语法:

using (Object1 obj1 = new Object1(), Object2 obj2 = new Object2())
{
    // Do something with obj1 & obj2
}

如果你这样做,obj1和obj2都将在块的末尾被处理。在你的情况下,这意味着两个对象都将被关闭并释放它们的句柄。然后,GC将在某个未来的垃圾回收中清理它们。

详情请参见MSDN关于使用的页面。


0

object2不会随着object1一起被销毁(释放)。然而,使用语句会创建一个单独的作用域块,因此object2在此时确实超出了作用域。它的释放只是不确定的。

另外,如果object2也是IDisposable,你可以这样做:

using (object1)
using (object2)
{
} // bookmark1

无论如何,正常的垃圾回收规则仍然适用:对象的托管资源(内存)仍然以正常方式处理。使用/IDisposable仅释放非托管资源。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接