C Sharp Programming/Object Lifetime

Introduction
All computer programs use up memory, whether that is a variable in memory, opening a file or connecting to a database. The question is how can the runtime environment reclaim any memory when it is not being used? There are three answers to this question:


 * If you are using a managed resource, this is automatically released by the Garbage Collector
 * If you are using an unmanaged resource, you must use the IDisposable interface to assist with the cleanup
 * If you are calling the Garbage Collector directly, by using method, it will be forced to tidy up resources immediately.

Before discussing managed and unmanaged resources, it would be interesting to know what the garbage collector actually does.

Garbage Collector
The garbage collector is a background process running within your program. It is always present within all .NET applications. Its job is to look for objects (i.e. reference types) which are no longer being used by your program. If the object is assigned to null, or the object goes out of scope, the garbage collector will mark the object be cleaned up at some point in the future, and not necessarily have its resources released immediately!

Why? The garbage collector will have a hard time keeping up with every de-allocation you make, especially at the speed the program runs and therefore only runs when resources become limited. Therefore, the garbage collector has three "generations".


 * Generation 0 - the most recently created objects
 * Generation 1 - the mid-life objects
 * Generation 2 - the long term objects.

All reference types will exist in one of these three generations. They will firstly be allocated to Gen 0, then moved to Gen 1 and Gen 2 depending on their lifetime. The garbage collector works by removing only what is needed and so will only scan Gen 0 for a quick-fix solution. This is because most, if not all, local variables are placed in this area.

For more in-depth information, visit the MSDN Article for a better explanation.

Now you know about the garbage collector, let's discuss the resources that it is managing.

Managed Resources
Managed resources are objects which run totally within the .NET framework. All memory is reclaimed for you automatically, all resources closed and you are in most cases guaranteed to have all the memory released after the application closes, or when the garbage collector runs.

You do not have to do anything with them with regards to closing connections or anything, it is a self-tidying object.

Unmanaged Resources
There are circumstances where the .NET framework world will not release resources. This may be because the object references resources outside of the .NET framework, like the operating system, or internally references another unmanaged component, or that the resources accesses a component that uses COM, COM+ or DCOM.

Whatever the reason, if you are using an object that implements the interface at a class level, then you too need to implement the  interface too.

This interface exposes a method called. This alone will not help tidy up resources, as it is only an interface, so the developer must use it correctly in order to ensure the resources are released. The two steps are:


 * 1) Always call Dispose on any object that implements IDisposable as soon as you are finished using it. (This can be made easier with the  keyword)
 * 2) Use the finalizer method to call Dispose, so that if anyone has not closed your resources, your code will do it for them.

Dispose pattern
Often, what you want to clean up varies depending on whether your object is being finalized. For example, you would not want to clean up managed resources in a finalizer since the managed resources could have been reclaimed by the garbage collector already. The dispose pattern can help you implement resource management properly in this situation:

Applications
If you are coming to C# from Visual Basic Classic you will have seen code like this:

Note that neither oFSO nor oFile are explicitly disposed of. In Visual Basic Classic this is not necessary because both objects are declared locally. This means that the reference count goes to zero as soon as the function ends which results in calls to the Terminate event handlers of both objects. Those event handlers close the file and release the associated resources.

In C# this doesn't happen because the objects are not reference counted. The finalizers will not be called until the garbage collector decides to dispose of the objects. If the program uses very little memory this could be a long time.

This causes a problem because the file is held open which might prevent other processes from accessing it.

In many languages the solution is to explicitly close the file and dispose of the objects and many C# programmers do just that. However, there is a better way: use the using statement:

Behind the scenes the compiler turns the using statement into  ...  and produces this intermediate language (IL) code:

Notice that the body of the Read function has been split into three parts: initialisation, try, and finally. The finally block includes code that was never explicitly specified in the original C# source code, namely a call to the destructor of the Streamreader instance.

See Understanding the 'using' statement in C# By TiNgZ aBrAhAm.

See the following sections for more applications of this technique.

Resource Acquisition Is Initialisation
The application of the using statement in the introduction is an example of an idiom called Resource Acquisition Is Initialisation (RAII).

RAII is a natural technique in languages like Visual Basic Classic and C++ that have deterministic finalization, but usually requires extra work to include in programs written in garbage collected languages like C# and VB.NET. The using statement makes it just as easy. Of course you could write the try..finally code out explicitly and in some cases that will still be necessary. For a thorough discussion of the RAII technique see HackCraft: The RAII Programming Idiom. Wikipedia has a brief note on the subject as well: Resource Acquisition Is Initialization.

Work in progress: add C# versions showing incorrect and correct methods with and without using. Add notes on RAII, memoization and cacheting (see OOP wikibook).