您是否必须使用Dispose方法释放托管资源?

时间:2019-10-18 13:06:29

标签: c# .net

this MSDN资源之后,代码

using System;

class BaseClass : IDisposable
{
   // Flag: Has Dispose already been called?
   bool disposed = false;

   // Public implementation of Dispose pattern callable by consumers.
   public void Dispose()
   { 
      Dispose(true);
      GC.SuppressFinalize(this);           
   }

   // Protected implementation of Dispose pattern.
   protected virtual void Dispose(bool disposing)
   {
      if (disposed)
         return; 

      if (disposing) {
         // Free any other managed objects here.
         //
      }

      // Free any unmanaged objects here.
      //
      disposed = true;
   }

   ~BaseClass()
   {
      Dispose(false);
   }
}

关于释放托管资源/对象的评论。

据我所知,垃圾收集器可以做到这一点,但是在这里实际编写这样的代码是否是一种好习惯,因此我的意思是将对象的引用指向null?

我相信这是“处置”托管资源时可以做的最好的事情,尽管您在此过程中什么也做不了,因为垃圾收集器将进行实际的繁重工作,而不是将其引用设置为null。 (垃圾收集器会注意到未使用包含这些对象/资源的类本身(没有引用),这使该任务变得毫无意义)

谢谢!

2 个答案:

答案 0 :(得分:2)

请注意,处置对象不会释放已分配的内存。这只是一种指示对象可能拥有的非托管资源的使用终止的方式。

例如,如果您的对象拥有一个非托管资源(例如TCP套接字),则可以让垃圾收集器在运行时结束所有操作,但是该套接字在此之前可能一直处于活动状态,从而导致以下情况:您在给定的时间有许多打开的连接,而服务器拒绝了新的连接。

当您有SqlConnection时会发生这种情况。当您调用Dispose时,它实际上不会关闭SqlServer的套接字,而是将连接返回到可以重用的池中。如果不处理SqlConnection,则在并发系统上,有一段时间这些对象是要进行垃圾收集的候选对象,但是由于它们仍然保持连接,因此有时您将与SqlServer建立过多的连接,并且可能会开始拒绝新的。

与SqlTransaction类似的东西。如果在调用Commit或Rollback之前引发了异常,并且从未调用过Dispose,则该连接可能会锁定表,页面等上的锁,从而导致其他连接的性能下降。

即使调用Dispose,SqlConnection对象仍在内存中,等待收集,但是由于实际的套接字已返回到池中而无法使用。实际上,如果您Dispose并调用其任何方法,它将抛出ObjectDisposedException,表明该对象不再可用。

实现IDisposable的对象或者拥有未使用的资源,或者拥有其他拥有未使用的资源的对象。因此,如果编写拥有SqlConnection的存储库类,则将需要实现级联Dispose调用。

答案 1 :(得分:0)

来自the same page

  

该方法的主体由两个代码块组成:

     
      
  • 释放非托管资源的块。不管dispose参数的值如何,该块都会执行。

  •   
  • 一个释放托管资源的条件块。如果dispose的值为true,则执行此块。它释放的托管资源可以包括:

         
        
    • 实现IDisposable的托管对象。条件块可以   用于调用其Dispose实现。如果您使用了保险箱   包装非托管资源的句柄,应调用   SafeHandle.Dispose(Boolean)实现在这里。

    •   
    • 消耗大量内存或稀缺资源的受管对象   资源。在Dispose方法中显式释放这些对象   释放它们的速度比不确定地回收它们的速度快   通过垃圾收集器。

    •   
  •   

因此,您当然应该释放所有也可以使用的托管对象,但是您可以可以释放所有使用大量内存或稀缺资源的托管对象。