When should I use "using" blocks in C#? [duplicate]
Some objects need some action to be taken when you have finished with them. Usually this is because the object uses some kind of resource that needs to be disposed of. For example, if you have a file object of class File, and this object opens a file from the file system, the file in the file system will need to be closed again.
If you just left the file object, and forgot to call file.Close() it wouldn't be cleaned up until the Garbage Collector (GC) ran and worked out nothing was still using the file object. When the Garbage Collector runs should be left to the Common Language Runtime (CLR) to decide. If the GC doesn't run for quite a while after you have finished with the file, the file could remain open potentially for a long time. This can pose a big problem if there are many file objects, or if something wants to open a file, but can't because the file object you left is still hanging around.
To solve this problem, C# has the IDisposable interface. This has one method called Dispose. Classes that require some cleanup implement this Dispose method. This gives you a standard way for cleaning up any objects that use resources. There are a lot of classes that need to have Dispose called. The problem with this is that code gets covered with calls to Dispose, and they are tricky to follow because the place where you new'ed the object and call Dispose to clean it up are different. So, you had to look around the code a lot and be very careful to check there were calls to Dispose in the right place.
To solve this problem C# introduced the 'using' keyword. You can put a 'using' keyword around where you new an object, and this ensures Dispose will be called on it for you. It guarantees that Dispose will be called whatever happens... even if there is an exception thrown within the body of the using statement.
So, you should use 'using' when you want to be sure an object that allocates resources will be cleaned up.
using can only be used for objects that are declared on the stack, i.e. in a function. It doesn't work for objects that are declared as members of a class. For them, you have to call Dispose yourself. You may have to implement Dispose in your class so that in can call Dispose on any member objects it has that require it.
Common objects that need using called on them are: Files, Database connections, Graphics objects such as Pen and Brush.
Sometimes it is also used when you want two operations to happen together. For example if you want to write a log statement when a block of code is entered and when it exits you could write a log class that you could use like this:
using( Log log = new Log("Doing stuff") )
{
// Stuff
}
The constructor for the log class could be made to write out the message, and the Dispose method could also write it out. Implement the finalizer (~Log) to assert if the Dispose method doesn't get called to ensure the 'using' is remembered around the 'new Log'.
When the SomeType
class implements IDisposable
.
Use using
whenever the type implements IDisposable
, unless you're going to wrap it in a try
/catch
block anyway, then you might as well (depending on what look you prefer) use a finally
block.