Introduction
The using
keyword is well known to C# developers. Its main purpose, the using
directive, is to create a shortcut to namespaces used in the code, but it's not the only purpose. using
can also be used to access an object in a bounded scope if this object's type implements the IDisposable
interface, which means it contains a public Dispose()
method.
Background
There are two types of object resources: managed and unmanaged:
- Managed Resource - A .NET Framework object, built only from .NET Framework code, without any external references (For example:
string
, integer
). The Garbage Collector handles managed resources, and releases them when they are not in use.
- Unmanaged Resource - An object inside or outside the .NET Framework, which uses external code (For example: file handles, streams, DB connections). The Garbage Collector can't handle unmanaged resources, so we need to release them manually.
The Dispose()
method is used to manually release all the resources of an object. It is useless for objects that contain only managed resources, which are already automatically released by the Garbage Collector.
On the other hand, it is useful for objects that contain unmanaged resources:
- Free resources held by an object.
- Prepare object for reuse.
Using the Code
Assume we have a class called MyClass
. This class implements the IDisposable
interface, which means it contains a public Dispose()
method. It also has another public
method – DoSomething()
:
class MyClass : IDisposable
{
public void DoSomething()
{
}
public void Dispose()
{
}
}
With the using
statement, we can create an instance of MyClass
in a bounded scope:
static void Main(string[] args)
{
using (MyClass myClazz = new MyClass())
{
myClazz.DoSomething();
}
}
Inside the using
statement, we can use myClazz
as a regular instance of MyClass
– in this case, call its public
method. Outside the using
statement, myClazz
doesn't exist.
What happens behind the scenes? Actually, it's very simple. The C# compiler will translate the above using
statement at compile time into something like this:
static void Main(string[] args)
{
{
MyClass myClazz = new MyClass();
try
{
myClazz.DoSomething();
}
finally
{
IDisposable dis = myClazz as IDisposable;
if (dis != null)
{
dis.Dispose();
}
}
}
}
The MyClass
instance is used inside a try
block. At the end of the use, the finally
block is called. Here, we dispose the instance, by calling the Dispose()
method of MyClass
.
Notice the extra braces around the code. They are used to create the bounded scope for the object.
Points of Interest
The main advantage of the using
statement is resources releasing management. Usually, the .NET Framework Garbage Collector controls resources releasing. With the using
statement, we can take the control:
- Decide when resources should be released
- Implement the
Dispose()
method, and then decide exactly which resources will be released
This way, the only resources we keep will be those we really need.
Notice
This article, and more about programming can be found in my blog here.
History
- 08.05.09 - Third version - Added background information about
Dispose()
, managed and umnanaged resources. Thanks Glen Harvy, xlg for your comments
- 01.05.09 - Second version - thanks PIEBALDconsult for your comment
- 29.04.09 - Original version