Tuesday, January 15, 2013

C# - using

Every C# developer is familiar with the "using" syntax. But, what does "using" actually do and what are the benefits of using it?

Source from MSDN: Provides a convenient syntax that ensures the correct use of IDisposable objects.
For the object which implement IDisposable, we can use the "using" syntax on it. But, before that, the question is why and when do we need to implement IDisposable?

For the objects which use unmanaged or native resources such as file system, COM objects, network, database, any hardware related or third party component or library or etc, we need to ensure those resources to be released once we no longer need it. Otherwise, we are very likely in encountering memory leak problem.

We implement IDisposable in order to have the Dispose method for us to call to flag or indicate our object is no longer in used, so that Garbage Collector will prioritize which object to be finalized first.

Therefore, the "using" syntax is actually used to ensure the used object is dispose correctly. How to ensure that? With the following code:

using (SqlConnection sqlConn = new SqlConnection(connString))
using (SqlCommand sqlCmd = new SqlCommand(cmdText, sqlConn))
{
    sqlCmd.ExecuteNonQuery();
}

The compiler will translate it into:

{ //Create a new scope for SqlConnection
    SqlConnection sqlConn = new SqlConnection(connString);
    try
    {
        { //Create a new scope for SqlCommand
            SqlCommand sqlCmd = new SqlCommand(cmdText, sqlConn);
            try
            {
                sqlCmd.ExecuteNonQuery();
            }
            finally
            {
                if (sqlCmd != null)
                    ((IDisposable)sqlCmd).Dispose();
            }
        }
    }
    finally
    {
        if (sqlConn != null)
            ((IDisposable)sqlConn).Dispose();
    }
}


You save a lot of time in writing that long code as above by just using the "using".
There is a try... catch... implemented for you. In case anything wrong happen during the execution of the code that work with unmanaged resource, it will make sure it get disposed.

Imagine with the following code without the try... catch... and also without the using block, an error occur at the highlighted line of code sqlCmd.ExecuteNonQuery( ). The Dispose( ) method after the error will never be reached, and the instantiated unmanaged resource will get hold up.


SqlConnection sqlConn = new SqlConnection(connString);
SqlCommand sqlCmd = new SqlCommand(cmdText, sqlConn);
sqlCmd.ExecuteNonQuery();
sqlConn.Close();
sqlCmd.Dispose();
sqlConn.Dispose();


Back to the code translation of "using", you can see any codes within the "using" block are group with context or scope { }

I have one doubt yet to confirm, when the code execution exit the scope, any object which is instantiated within that scope will be collected at the same time with the object had been called for dispose by Garbage Collector or not? For example,

using (SqlConnection sqlConn = new SqlConnection(connString))
{
    SqlCommand sqlCmd = new SqlCommand(cmdText, sqlConn);
    sqlCmd.ExecuteNonQuery();
}


Will SqlCommand object get collected by the Garbage Collector after the code execution exit the using block?

I tried to use CLR profiler tool but I can't find my answer and I don't know any other memory profiler tool can help, please leave a comment if you know the answer.

However, base on the Garbage Collector behavior, what I am certain is the objects within the scope will definitely be collected by the Garbage Collector, just that the priority is not higher than the object which had been called for dispose. The reason is it is impossible for any other code which is outside from one scope to use the object in this one scope. Since the object in one scope is not possible to be used by any other scope from outside, therefore the object will not be referenced and it will be cleared after some time.

In summary, it will be the best if we can always call the Dispose method whenever we do not need the object. Relying on scope is still acceptable but not efficient enough. Recommended way is to use "using" whenever possible.


No comments:

Post a Comment

Send Transactional SMS with API

This post cover how to send transactional SMS using the Alibaba Cloud Short Message Service API. Transactional SMS usually come with One Tim...