"using"关键字是否意味着对象被处理并且GC'了?

now*_*ed. 35 .net c# garbage-collection dispose

我今天和我的同事进行了一次对话,她说她刚刚了解了使用该using声明背后的原因.

 //Using keyword is used to clean up resources that require disposal (IDisposable interface). 

 using (StreamReader reader = new StreamReader(@"C:\test.txt")) 
 { 
 string line = reader.ReadLine(); 
 } 
Run Code Online (Sandbox Code Playgroud)

我指出,除非GC决定这样做,否则该物体被标记为"可以处置"但实际上没有处理和垃圾收集.

她回答说,一旦using语句结束,对象将自动处理,因为using语句被转换为try-catch-finally块.因此,对象必须放在using语句的最后.

我对此感到困惑,因为我知道使用using语句并不能保证对象被GC收集.所有发生的事情都是Dispose()调用该方法.GC无论如何都决定GC.但当她要求证明时,我找不到任何证据.

有谁知道这是如何工作的,以及如何证明它?

Lua*_*aan 41

你在谈论两件截然不同的事情.

一旦using-block结束,该对象将被释放.这并没有说什么时候它是垃圾收集.释放堆内存的唯一时间是发生垃圾收集 - 这只发生在内存压力下(除非您GC.Collect明确使用).

处理对象只是意味着调用它的Dispose方法.这通常意味着释放稀缺资源或本机资源(实际上,所有稀缺资源都是本机 - 套接字,文件......).现在,在您的情况下,一次性对象的生命周期在范围上是有限的,因此理论上可以在using-block结束时立即收集- 但是,这在实践中并不真正发生,因为.NET运行时尝试避免收藏 - 它们很贵.因此,在跨越内存分配阈值之前,即使堆上有死对象,也不会发生任何集合.

那有什么意义Dispose呢?与托管内存无关.你并不真正关心托管内存,你不应该期望Dispose实际上会被调用 - 它不一定是.那唯一拥有由运行时调用是终结了,你就永远只能使用原生资源的配置-其实,有没有保证,如果仍然由时间存在,您有一个参考对象的终结器运行 - 那时托管内存可能已经被回收了.这就是你永远不会在终结器中处理托管资源的原因.

所以是的,她完全正确.关键是IDisposable与垃圾收集器无关.处置并不意味着收集垃圾.


Sri*_*vel 12

她对钱的using说法是正确的只是一个合成糖try/finally{obj.Dispose();}.using语句确保将丢弃对象.(将调用Dispose方法)但它与垃圾回收没有关系.

看看这个理解使用语句

简短的回答:所以现在我们知道using语句只是调用Dispose而且除此之外什么都不做,请记住,Dispose方法并不比任何其他方法特别.这只是一种方法而且就是这样.所以它与垃圾收集无关.有趣的是"垃圾收集器"甚至不知道Dispose方法或IDisposable.

希望这可以帮助

  • 除非你明确地将它设置为"null",否则对象不会变为"null".如果你在某个地方有对象的实时引用,那么对象将存在于内存中,尽管对象被处理掉了. (3认同)
  • +1`"垃圾收集器"甚至不知道Dispose方法或IDisposable` (3认同)
  • @PhilSandler是的我措辞错了,它是`try ... finally {Dispose()}`的合成糖.这有道理吗? (3认同)