Я действительно хочу вытащить это из головы. Посмотрите ниже кода:
using (DataTable resultTable = DBUtility.GetSingleDBTableResult(connectionString, "SELECT * FROM MyDBTable")) {
List<string> resultsList = new List<string>();
foreach (DataRow dataRow in resultTable.Rows) {
resultsList.Add(dataRow[0].ToString());
}
return resultsList;
}
Таблица данных расположена? Кто-то может объяснить, как это переводится в блок попытки/выгоды/наконец? MSDN указывает, что, если исключение произошло, Расположить метод все еще назовут, но что относительно оператора возврата?
Или если я просто использую ниже кода:
List<string> resultsList = new List<string>();
using (DataTable resultTable = DBUtility.GetSingleDBTableResult(connectionString, "SELECT * FROM MyDBTable")) {
foreach (DataRow dataRow in resultTable.Rows) {
resultsList.Add(dataRow[0].ToString());
}
}
return resultsList;
Вероятно, второй должен использоваться, но мне просто нужно просвещение :). Объясните.Спасибо.
using
оператор - это просто синтаксический сахар, и он переводится в блок try / finally. Начиная с вашего кода, вот как компилятор C # преобразует блок using
в блок try / finally.
try
{
DataTable resultTable = DBUtility.GetSingleDBTableResult(connectionString, "SELECT * FROM MyDBTable");
List<string> resultsList = new List<string>();
foreach (DataRow dataRow in resultTable.Rows)
{
resultsList.Add(dataRow[0].ToString());
}
return resultsList;
}
finally
{
resultTable.Dispose();
}
Как видно из кода, resultTable удаляется наверняка независимо от оператора return. Блок using только обеспечивает удаление объекта после области видимости.
Ваш первый код мне кажется нормальным, и его не нужно менять.
Использование
не позволяет перехватить исключения, оно просто гарантирует вызов .Dispose ()
.
Это потому, что
использование (ResourceType resource = new ResourceType ())
эквивалентно:
ResourceType resource;
try
{
resource = new ResourceType();
/* The insides of the using block */
}
finally
{
resource.Dispose();
}
Вызов .Dispose ()
всегда будет быть оцененным. Вызов Dispose
оценивается даже при возврате в пределах своего с использованием блока
(до того, как он «действительно» вернется). Вызов Dispose
оценивается даже в случае возникновения исключения.
Однако, если генерируется исключение, это исключение по-прежнему будет препятствовать оценке последующих строк кода (за исключением .Dispose ()
, который всегда вычисляется) .
Таким образом, если возникает исключение, ваш return
не будет возвращен ни в одном из ваших операторов, но ваш DataTable
все равно будет удален.
Если вы хотите гарантировать, что возврат произойдет даже при возникновении ошибки, вы должны сделать что-то вроде этого:
List resultsList = new List();
try
{
using (DataTable resultTable = DBUtility.GetSingleDBTableResult(connectionString, "SELECT * FROM MyDBTable"))
{
foreach (DataRow dataRow in resultTable.Rows)
{
resultsList.Add(dataRow[0].ToString());
}
}
}
catch
{
}
return resultsList;
DataTable удаляется (вызывается .Dispose
) в обоих случаях.
Он переведен в try / finally
, при этом Dispose
вызывается в finally
. Наконец, как следует из названия, вызывается, даже когда вы вызываете return
.
В обоих ваших примерах будет вызываться Dispose
. Это потому, что оператор using расширяется до блока try / finally.
Прочтите Спецификацию языка C # (8.13 Оператор using), чтобы узнать о различных сценариях (для ссылочных типов, типов значений, не допускающих значения NULL, и динамических типов).
Поскольку DataTable
является ссылочным типом, ваш первый образец будет расширен до следующего:
{
DataTable resultTable = DBUtility.GetSingleDBTableResult(connectionString, "SELECT * FROM MyDBTable");
try {
List<string> resultsList = new List<string>();
foreach (DataRow dataRow in resultTable.Rows) {
resultsList.Add(dataRow[0].ToString());
}
return resultsList;
}
finally {
if (resultTable != null) ((IDisposable)resultTable).Dispose();
}
}