C # использование заявления - PullRequest
7 голосов
/ 06 июля 2010

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

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;
}

Утилизируется ли дата?Может кто-нибудь объяснить, как это переводится в блок try / catch / finally?MSDN заявляет, что если произошло исключение, метод Dispose будет по-прежнему вызываться, но как насчет оператора return?

Или я должен просто использовать приведенный ниже код:

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;

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

Ответы [ 4 ]

5 голосов
/ 06 июля 2010

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 точно удаляется независимо от возвратазаявление.Блок using только гарантирует, что объект будет удален после области действия.

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

4 голосов
/ 06 июля 2010

Using не не перехватывает исключения, он просто гарантирует вызов .Dispose().

Это потому, что

using (ResourceType resource = new ResourceType()) эквивалентно:

ResourceType resource;
try 
{
     resource = new ResourceType();
     /* The insides of the using block */
}
finally
{
    resource.Dispose();
}

Вызов .Dispose() будет всегда .Вызов Dispose даже оценивается, если вы вернетесь в свой блок using (до того, как он "действительно" вернется).Вызов 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;
1 голос
/ 06 июля 2010

В обоих ваших примерах будет вызываться Dispose.Это связано с тем, что оператор using расширяется до блока try / finally.

Прочтите спецификацию языка C # (8.13 Оператор using), чтобы найти различные сценарии (для ссылочных типов, необнуляемые типы значений и динамические типы).

Поскольку 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 голос
/ 06 июля 2010

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

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

...