Resource Management

Garbage Collector

Unmanaged Resources

Using

The using keyword can be used as a syntax for deterministically managing the scope of an object. The use of using with a scoped resource forces the resource to be released at the end of the scope that the resource is valid for. Normally you would have to wait for the garbage collector to decide the resource was not being used and dispose of it, but using gives an explicit direction that the resource is no longer needed and any reference to it can be removed from the current run time.

Resource management with using does not free the memory but it does help with managing limited pools of resources (for example database connections) by marking unneeded resources allowing for the resource pool to be replenished. An object which falls out of scope and owns resources, which is then garbage collected will never has its resources released because the garbage collector is not responsible for resource management. For example, in the database connections example, the database connection pool will never receive a message that a garbage collected connection from its pool is done with the connection if the memory for that resource is disposed of without it releasing its resources.

Resource management with using only works with only work with objects that implement the IDisposable interface. This interface contains a single method Dispose that is called automatically when the resource declared with using goes out of scope, disposing of it.

The use of using within methods, for resource management, is completely separate from using for imports at the top of a file.

Using blocks

using blocks are one syntax for deterministically describing the scope of an object. You can ensure an object is limited to a particular scope by declaring it with the using keyword before the block in which it is used. This will cause the object’s resources to be released at the end of the block.

using(MyObject myObject = new MyObject())
{
  myObject.MyMethod();
}
// myObject is disposed (Dipose() called implicitly)

You can define multiple using scope declarations in a single statement by separating the declarations. You don’t have to use nested using statements.

using(System.IO.StreamReader r = new System.IO.StreamReader(""), r2 = new System.IO.StreamReader(""))
{
  // use stream readers
}

Using variables

You can also limit object scope within a block by placing the using statement within an already existing scope. The object will then be disposed of when the program exits that scope. This is a newer syntax version of the using blocks above for greater ease of resource management.

if(true)
{
  using var myObject = new MyObject();
}
// myObject is disposed (Dipose() called implicitly)

Try / Finally Equivalents

using blocks are similar to a try { } finally { } block where something is used in the try and then disposed of in the finally. Thus, the following example:

var con = new SqlConnection();
try
{
  con.execute();
}
finally
{
  con.Dispose();
}

Is roughly equivalent to the example below where the Dispose method is called implicitly by using. The main difference being that using ensures that Dispose is called even when an exception occurs.

using(SqlConnection con = new SqlConnect())
{
  con.execute();
}

Finalizer

A finalizer is an optional method which executes when an object is garbage collected. Adding a finalizer to an object is optional.

If an object does have a finalizer the finalizer method is added to a finalization queue during garbage collection. This adds significant overhead to the GC which means you should only use it as a safety net for freeing unmanaged resources. The finalizer exists in case the user of an IDisposable doesn’t correctly release its resources.

You can create a finalizer method for a class with the name of the class preceded by a ~ tilde with no arguments.

public class MyClass
{
  ~MyClass()
  {
    // finalization logic
  }
}

IDisposable

The IDisposable interface implements a single method called Dipose which is called automatically when a resource managed object that implements it goes out of scope.

If an object implements IDisposable this is an indication that it holds some valuable resource and should be released when possible. It’s up the resource consumer to correctly release the resource with the Dispose method.

public interface IDisposable
{
  void Dispose();
}

You can stop the garbage collector from calling your class’s Finalize method IF the Dipose was successfully triggered by using the SuppressFinalize method on the GC object. You should do this if your class’s finalizer and Dispose method essentially accomplish the same thing, as having an unnecessary finalizer is not good due to its added overhead.

public void Dipose()
{
  // do some disposal
  GC.SuppressFinalize(true);
}