1

Following this MSDN resource, the code

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);
   }
}

has a comment about freeing managed resources/objects.

As far as I know, the garbage collector will do that, but is it good practice to actually write such code there, and by such I mean pointing the objects's references to null?

I believe that's the best you can do at "disposing" of a managed resource, although you don't achieve anything in the process, as the garbage collector will do the actual heavy lifting, not you setting their references to null. (The garbage collector will notice that the class itself holding these objects/resources is not used (no references), making this task meaningless)

Thanks!

Community
  • 1
  • 1
SpiritBob
  • 2,355
  • 3
  • 24
  • 62
  • 1
    GC will only consider those objects eligible for collection if there are no live, rooted, references to them. You can still hold on to (reference) a disposed object. So yes, there might be a point in setting those variables to null, but you might instead want to look at why you're holding on to the disposed object, if you end up having a memory problem because of this. – Lasse V. Karlsen Oct 18 '19 at 13:09

2 Answers2

2

Note that disposing an object does not frees the allocated memory. It just a way to indicate the end of use of unmanaged resources that your object may be owning.

For example, if your object owns an unmanaged resource like for example a TCP socket, you can just let the garbage collector end everything when it runs, but the socket will be potentially alive until that happen, leading to a situation in which you have many open connections at a given time and the server is rejecting new ones.

This happens when you have a SqlConnection. When you call Dispose, it actually does not close the socket to SqlServer, but returns the connection to a pool where it can be reused. If you do not dispose SqlConnection, on a concurrent system there will be a moment where those objects are candidates to be garbage-collected, but because they are still there holding a connection, at some point you will have too many connections to SqlServer and it may start rejecting the new ones.

Similar thing with a SqlTransaction. If an exception is thrown before you call Commit or Rollback and Dispose is never called, the connection will potentially hold locks on tables, pages, etc... causing performance degradation in other connections.

Even if you call Dispose, a SqlConnection object is still in memory, waiting to be collected, but unusable because the actual socket was returned to a pool. In fact if you Dispose and call any of its methods, it will throw an ObjectDisposedException, indicating that the object is unusable anymore.

And object that implements IDisposable, either owns unamanged resources, or owns other objects that owns unamanged resources. So if you write a repository class that owns a SqlConnection, you will need to implement a cascade Dispose call.

Vlad
  • 802
  • 1
  • 10
  • 23
1

From the same page:

The body of the method consists of two blocks of code:

  • A block that frees unmanaged resources. This block executes regardless of the value of the disposing parameter.

  • A conditional block that frees managed resources. This block executes if the value of disposing is true. The managed resources that it frees can include:

    • Managed objects that implement IDisposable. The conditional block can be used to call their Dispose implementation. If you have used a safe handle to wrap your unmanaged resource, you should call the SafeHandle.Dispose(Boolean) implementation here.

    • Managed objects that consume large amounts of memory or consume scarce resources. Freeing these objects explicitly in the Dispose method releases them faster than if they were reclaimed non-deterministically by the garbage collector.

So certainly you should free any managed objects that are also disposable, but you could also release any managed objects that use lots of memory or scarce resources.

D Stanley
  • 149,601
  • 11
  • 178
  • 240
  • But how do you free managed resources such as large list collections other than setting them to a null reference? – SpiritBob Oct 18 '19 at 13:16
  • *Why* do we need to move this data here, clearly it lives on the MSDN site. TBH, how is this of value to anyone as over 90% of the post is just from the site. – Trevor Oct 18 '19 at 13:23
  • @SpiritBob You just set the reference to null, which doesn't really free the memory directly but lets the GC do it sooner. But disposing of other disposable objects is more important IMHO. – D Stanley Oct 18 '19 at 13:37
  • @Çöđěxěŕ It answers the question, doesn't it? Why should we have to restate the official documentation in our own words? – D Stanley Oct 18 '19 at 13:40
  • It's _not_ a link-only answer, that's the point. I highlighted that the answer is found _in the same page that the OP linked to_, and included the relevant text that answers the question. – D Stanley Oct 18 '19 at 13:45
  • From [how to answer](https://stackoverflow.com/help/how-to-answer): "Links to external resources are encouraged, but please add context around the link so your fellow users will have some idea what it is and why it’s there. ***Always quote the most relevant part of an important link***, in case the target site is unreachable or goes permanently offline." – D Stanley Oct 18 '19 at 13:49
  • https://stackoverflow.com/a/16602050/1797425 | https://stackoverflow.com/questions/898828/finalize-dispose-pattern-in-c-sharp/2061387 | https://stackoverflow.com/questions/732864/finalize-vs-dispose/8298114#8298114 we need more of these questions right? – Trevor Oct 18 '19 at 13:51
  • @Çöđěxěŕ hey there. I read that question before posting this one, but even after reading it all, I still felt compelled to open this one and ask specifically if there is any use in setting managed resources to **null** or not. And why bring the negative attitude? I'm perfectly happy with their answer! – SpiritBob Oct 18 '19 at 13:52
  • I'm just asking a question? Provided links alone are more than enough and explain in *detail* is all I am saying. – Trevor Oct 18 '19 at 13:56
  • @Çöđěxěŕ The proper way to handle that is to vote to close as a duplicate. – D Stanley Oct 18 '19 at 13:56
  • @DStanley it wasn't the answer, we have these questions all over on the same topic. On the right side of screen, there's 3 alone in the `Linked` section. – Trevor Oct 18 '19 at 13:56