Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>It's important to separate disposal from garbage collection. They are completely separate things, with one point in common which I'll come to in a minute.</p> <p><strong><code>Dispose</code>, garbage collection and finalization</strong></p> <p>When you write a <code>using</code> statement, it's simply syntactic sugar for a try/finally block so that <code>Dispose</code> is called even if the code in the body of the <code>using</code> statement throws an exception. It <em>doesn't</em> mean that the object is garbage collected at the end of the block.</p> <p>Disposal is about <em>unmanaged resources</em> (non-memory resources). These could be UI handles, network connections, file handles etc. These are limited resources, so you generally want to release them as soon as you can. You should implement <code>IDisposable</code> whenever your type "owns" an unmanaged resource, either directly (usually via an <code>IntPtr</code>) or indirectly (e.g. via a <code>Stream</code>, a <code>SqlConnection</code> etc).</p> <p>Garbage collection itself is only about memory - with one little twist. The garbage collector is able to find objects which can no longer be referenced, and free them. It doesn't look for garbage all the time though - only when it detects that it needs to (e.g. if one "generation" of the heap runs out of memory).</p> <p>The twist is <em>finalization</em>. The garbage collector keeps a list of objects which are no longer reachable, but which have a finalizer (written as <code>~Foo()</code> in C#, somewhat confusingly - they're nothing like C++ destructors). It runs the finalizers on these objects, just in case they need to do extra cleanup before their memory is freed.</p> <p>Finalizers are almost always used to clean up resources in the case where the user of the type has forgotten to dispose of it in an orderly manner. So if you open a <code>FileStream</code> but forget to call <code>Dispose</code> or <code>Close</code>, the finalizer will <em>eventually</em> release the underlying file handle for you. In a well-written program, finalizers should almost never fire in my opinion.</p> <p><strong>Setting a variable to <code>null</code></strong></p> <p>One small point on setting a variable to <code>null</code> - this is almost never required for the sake of garbage collection. You might sometimes want to do it if it's a member variable, although in my experience it's rare for "part" of an object to no longer be needed. When it's a local variable, the JIT is usually smart enough (in release mode) to know when you're not going to use a reference again. For example:</p> <pre><code>StringBuilder sb = new StringBuilder(); sb.Append("Foo"); string x = sb.ToString(); // The string and StringBuilder are already eligible // for garbage collection here! int y = 10; DoSomething(y); // These aren't helping at all! x = null; sb = null; // Assume that x and sb aren't used here </code></pre> <p>The one time where it <em>may</em> be worth setting a local variable to <code>null</code> is when you're in a loop, and some branches of the loop need to use the variable but you know you've reached a point at which you don't. For example:</p> <pre><code>SomeObject foo = new SomeObject(); for (int i=0; i &lt; 100000; i++) { if (i == 5) { foo.DoSomething(); // We're not going to need it again, but the JIT // wouldn't spot that foo = null; } else { // Some other code } } </code></pre> <p><strong>Implementing IDisposable/finalizers</strong></p> <p>So, should your own types implement finalizers? Almost certainly not. If you only <em>indirectly</em> hold unmanaged resources (e.g. you've got a <code>FileStream</code> as a member variable) then adding your own finalizer won't help: the stream will almost certainly be eligible for garbage collection when your object is, so you can just rely on <code>FileStream</code> having a finalizer (if necessary - it may refer to something else, etc). If you want to hold an unmanaged resource "nearly" directly, <a href="http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.safehandle.aspx" rel="noreferrer"><code>SafeHandle</code></a> is your friend - it takes a bit of time to get going with, but it means you'll <a href="http://joeduffyblog.com/2008/02/17/idisposable-finalization-and-concurrency/" rel="noreferrer">almost</a> <a href="http://joeduffyblog.com/2005/12/27/never-write-a-finalizer-again-well-almost-never/" rel="noreferrer">never need to write a finalizer again</a>. You should usually only need a finalizer if you have a really direct handle on a resource (an <code>IntPtr</code>) and you should look to move to <code>SafeHandle</code> as soon as you can. (There are two links there - read both, ideally.)</p> <p>Joe Duffy has a <a href="http://joeduffyblog.com/2005/04/08/dg-update-dispose-finalization-and-resource-management/" rel="noreferrer">very long set of guidelines around finalizers and IDisposable</a> (co-written with lots of smart folk) which are worth reading. It's worth being aware that if you seal your classes, it makes life a lot easier: the pattern of overriding <code>Dispose</code> to call a new virtual <code>Dispose(bool)</code> method etc is only relevant when your class is designed for inheritance.</p> <p>This has been a bit of a ramble, but please ask for clarification where you'd like some :)</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload