Оператор использования C#

Я действительно хочу вытащить это из головы. Посмотрите ниже кода:

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;

Вероятно, второй должен использоваться, но мне просто нужно просвещение :). Объясните.Спасибо.

7
задан Alconja 6 July 2010 в 04:18
поделиться

4 ответа

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 только обеспечивает удаление объекта после области видимости.

Ваш первый код мне кажется нормальным, и его не нужно менять.

5
ответ дан 6 December 2019 в 23:00
поделиться

Использование не позволяет перехватить исключения, оно просто гарантирует вызов .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;
4
ответ дан 6 December 2019 в 23:00
поделиться

DataTable удаляется (вызывается .Dispose ) в обоих случаях.

Он переведен в try / finally , при этом Dispose вызывается в finally . Наконец, как следует из названия, вызывается, даже когда вы вызываете return .

1
ответ дан 6 December 2019 в 23:00
поделиться

В обоих ваших примерах будет вызываться 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();
    }
}
1
ответ дан 6 December 2019 в 23:00
поделиться
Другие вопросы по тегам:

Похожие вопросы: