During the code review the other day, the question arose of how to quickly close the use block. One camp said: "Once you are done with the object"; another, "someday before he goes out of scope."
In this particular example, there is a DataTable and a SqlCommand that should be deleted. We need to refer to one operator as well, and we need to iterate over 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 of SqlCommand as soon as you finish using it. Do not run potentially lengthy operations, such as iterating a table, inside another object using a 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, no matter what, and none of them is resource-intensive, so it is not important to dispose immediately.
I'm in camp 2. Where are you and why?
Edit:. Several people have indicated that the DataTable does not need to be deleted (see Corey Sunwold’s answer ), and that the first Camp 1 example is uglier than it should be. Here are a few revised examples that also take into account the fact that most of the time I have to set some properties in SqlCommand. If anyone has seen or can come up with a better example to support any 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 would agree that the readability argument is now significantly reduced and that this is not the best example of what I'm trying to ask. (This is especially true as soon as I tell you that SqlConnection is closed before the GetDataTable () method completes, and there are no measurable performance differences for the data used in this instance.) If I can add to my question it's late when there is any difference, do I delete the object immediately? For example, as Gregory Higley mentioned , a shared resource such as an OS descriptor.
Edit: (explaining my choice of answer) Many thanks to everyone who contributed to our opinions, examples, and other useful feedback! It seems that we split evenly, but what stands out among everyone is the idea that "Camp 1 is definitely right, but depending on the facility, Camp 2 may be in order." I meant that this is a general discussion about the disposal of all types of objects, but I chose a bad example to illustrate this. Since most of the discussion focused on this particular example, I chose an answer that gave me important information about the specific objects used, and proved that I need to carefully consider each object when making such a decision. (In any case, it would be difficult to choose the "best answer" to a question as vague as in my title). Future readers with the same dilemma, please see all the answers below, as many of them raise interesting points.