Во время обзора кода на днях возник вопрос о том, как быстро должен быть закрыт блок использования. Один лагерь сказал: «Как только вы закончите с объектом»; другой - «когда-нибудь, прежде чем он выйдет за рамки».
В этом конкретном примере есть объект DataTable и объект SqlCommand, которые должны быть удалены. Нам нужно ссылаться на оба в одном выражении, и нам нужно перебрать DataTable.
Лагерь 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();
}
}
Причина: утилизируйте SqlCommand, как только вы закончите с ним. Не запускайте потенциально длинные операции, такие как итерации таблицы, внутри блока using другого объекта.
Лагерь 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));
}
}
Причина: этот код намного чище. Все объекты гарантированно будут уничтожены, несмотря ни на что, и ни один из них не является действительно ресурсоемким, поэтому не важно уничтожать их немедленно.
Я в Лагере 2. Где ты и почему?
Редактировать: Несколько человек указали, что DataTable не нужно утилизировать (см. ответ Кори Санволд ) и что оригинальный пример в Лагере 1 более уродлив, чем должен быть. Вот некоторые пересмотренные примеры, которые также учитывают тот факт, что большую часть времени мне приходится устанавливать некоторые свойства в SqlCommand. Если кто-то видел или может придумать лучший пример в поддержку какой-либо позиции, поделитесь им.
Лагерь 1, версия 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));
}
Лагерь 2, версия 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));
}
}
Я думаю, что большинство людей согласятся с тем, что аргумент читабельности сейчас значительно уменьшен, и что это не лучший пример того, что я пытаюсь спросить. (Это особенно верно, если я скажу вам, что SqlConnection закрывается до выхода из метода GetDataTable (), и нет никаких ощутимых различий в производительности для данных, используемых в этом экземпляре.) Если я могу добавить к своему вопросу так поздно, есть ли случаи, когда это имеет значение, могу ли я избавиться от объекта немедленно? Например, , как упомянул Грегори Хигли, , общий ресурс, похожий на дескриптор ОС.
Редактировать: (Объясняя мой выбор ответа) Большое спасибо всем, кто высказал свое мнение, примеры и другие полезные отзывы! Кажется, мы разделены примерно на равные, но что следует из ответов каждого, так это идея, что «лагерь 1 определенно прав, но в зависимости от цели, лагерь 2 может быть в порядке». Я имел в виду, что это будет общее обсуждение избавления от всех типов объектов, но я выбрал плохой пример, чтобы проиллюстрировать это. Поскольку большая часть обсуждения была сосредоточена на этом конкретном примере, я выбрал ответ, который дал мне важную информацию о конкретных используемых объектах, и доказал, что мне нужно тщательно учитывать каждый объект при принятии такого рода решения. (В любом случае, было бы трудно выбрать «лучший ответ» на вопрос, столь же расплывчатый, как и мой заголовок.) Будущие читатели с такой же дилеммой, пожалуйста, посмотрите все ответы ниже, так как многие из них поднимают интересные вопросы.