在.NET中处理资源

时间:2010-07-09 16:00:08

标签: c# memory garbage-collection idisposable

我有一个愚蠢的问题,但我想在这里听到社区。

所以这是我的代码:

using (FtpWebResponse response = (FtpWebResponse)request.GetResponse()) 
{ 
      return true; 
} 

我的问题,是否与以下不同:

(FtpWebResponse)request.GetResponse();
return true;

哪一个更好? GC中哪一个和为什么?

5 个答案:

答案 0 :(得分:11)

第一个更好,但不是GC。 WebResponse实现IDisposable,因为它有需要释放的资源,例如网络连接,内存流等。IDisposable已经到位,因为作为消费者,您知道何时完成使用该对象,您可以调用Dispose 通知您已完成的课程,并且可以自行清理。

using模式实际上只是调用了Dispose。例如。你的第一个例子实际编译为:

FtpWebResponse response = (FtpWebResponse)request.GetResponse()
try
{
}
finally
{
    ((IDisposable)response).Dispose();
}
return true;

这与垃圾收集器是分开的。一个类也可以清理终结器中的资源,它可以从GC中调用,但是你不应该依赖它来实现这两个原因:

  1. 可能需要很长时间才能最终实现GC,这意味着这些资源无需充分理由就会消耗掉。
  2. 无论如何,它实际上可能无法清理终结器中的资源

答案 1 :(得分:7)

第一个更好。

不同之处在于using语句将对包含在其中的对象调用dispose。它将正确处理所持有的资源。

来自MSDN,使用声明:

  

提供方便的语法,确保正确使用IDisposable对象。

答案 2 :(得分:4)

我感谢您对此回复不感兴趣。但是,响应对象已创建,初始化并返回到您的代码,无论您是否需要它。如果你不处理它,那么它会消耗资源,直到GC最终完成它来完成它。

答案 3 :(得分:2)

我同意其他人的说法,但如果你对using()语法有这样的仇恨,你可以这样做:

((IDisposable)request.GetResponse()).Dispose();
return true; 

答案 4 :(得分:1)

GC并不关心除内存以外的任何内容,因此如果你有足够的内存并且没有消耗太多内存,那么它可能需要很长时间才能运行GC。在整个过程中,非托管资源(例如网络连接,文件句柄,数据库连接,图形处理等)仍然被等待GC的对象所束缚。这可能会导致您耗尽这些资源,并且GC将无视,因为它不会监视非托管资源。

因此,如果您将代码放在循环中并继续调用它,而不调用Dispose,您可能会发现它很快就会降低性能(争夺稀缺资源的进程)或者由于缺少非托管资源而导致异常。它取决于它的调用方式以及如何创建其他相关对象。您可以在完成实例后立即调用Dispose,而不是分析每种情况。

确实最终Dispose将被GC调用一个超出范围/不再被引用的对象,但这是不确定的。由于存在不确定性,您可以看到在测试与生产时资源免费获取的时间不同的结果,并导致在资源耗尽时无法分配资源的随机异常。如果您可以选择应用程序的一致确定性行为和不确定性,那么您可能需要确定性,除非您尝试混淆测试人员。