A question came up during a code review the other day about how quickly a using block should be closed. One camp said, 'as soon as you are done with the object'; the other, 'sometime before it goes out of scope'.
In this specific example, there are a DataTable and a SqlCommand object to be disposed. We need to reference both in a single statement, and we need to iterate the DataTable.
Camp 1:
List<MyObject> listToReturn = new List<MyObject>();
DataTable dt = null;
try
{
using (InHouseDataAdapter inHouseDataAdapter = new InHouseDataAdapter())
using (SqlCommand cmd = new SqlCommand())
{
dt = inHouseDataAdapter.GetDataTable(cmd);
}
foreach (DataRow dr in dt.Rows)
{
listToReturn.Add(new MyObject(dr));
}
}
finally
{
if (dt != null)
{
dt.Dispose();
}
}
Reasoning: Dispose the SqlCommand as soon as you are done using it. Don't start potentially long operations, such as iterating the table, within another object's using block.
Camp 2:
List<MyObject> listToReturn = new List<MyObject>();
using (InHouseDataAdapter inHouseDataAdapter = new InHouseDataAdapter())
using (SqlCommand cmd = new SqlCommand())
using (DataTable dt = inHouseDataAdapter.GetDataTable(cmd))
{
foreach (DataRow dr in dt.Rows)
{
listToReturn.Add(new MyObject(dr));
}
}
Reasoning: This code is much cleaner. All objects are guaranteed to be disposed no matter what, and none are really resource-intensive, so it is not important to dispose any immediately.
I'm in Camp 2. Where are you, and why?
Edit: Several people have pointed out that DataTable need not be disposed (see Corey Sunwold's answer) and that Camp 1's original example is uglier than it needs to be. Here are some revised examples that also take into account the fact that most of the time, I have to set some properties on the SqlCommand. If anyone has seen or can think of a better example to support either position, please share it.
Camp 1, version 2:
DataTable dt = null;
using (InHouseDataAdapter inHouseDataAdapter = new InHouseDataAdapter(_connectionString))
using (SqlCommand cmd = new SqlCommand("up_my_proc"))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("@class_id", 27);
dt = inHouseDataAdapter.GetDataTable(cmd);
}
foreach (DataRow dr in dt.Rows)
{
listToReturn.Add(new MyObject(dr));
}
Camp 2, version 2:
using (InHouseDataAdapter inHouseDataAdapter = new InHouseDataAdapter(_connectionString))
using (SqlCommand cmd = new SqlCommand("up_my_proc"))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("@class_id", 27);
DataTable dt = inHouseDataAdapter.GetDataTable(cmd);
foreach (DataRow dr in dt.Rows)
{
listToReturn.Add(new MyObject(dr));
}
}
I think most people will agree that the readability argument is now much reduced, and that this is not the best example of what I am trying to ask. (That is especially true once I tell you that the SqlConnection is closed before the GetDataTable() method exits, and there is no measurable performance difference for the data used in this instance.) If I may add to my question this late, are there instances where it does make a difference whether I dispose the object immediately? For example, as Gregory Higley mentioned, a shared resource like an OS handle.
Edit: (Explaining my choice of answer) Many thanks to all who contributed opinions, examples, and other helpful feedback! We seem to be split about evenly, but what stands out from everyone's answers is the idea that 'camp 1 is definitely right, but depending on the object, camp 2 may be okay'. I meant this to be a general discussion of disposal of all types of objects, but I chose a bad example to illustrate it. Since much of the discussion focused on that particular example, I have chosen the answer that gave me important information about the specific objects in use, and proved that I need to consider each object carefully when making this kind of decision. (It would be difficult to choose a 'best answer' to a question as vague as what is in my title, anyway.) Future readers with the same dilemma, please see all the answers below, as many of them raise interesting points.