Выполняет ли оператор C # с помощью try / finally? - PullRequest
17 голосов
/ 26 апреля 2010

Предположим, у меня есть следующий код:

private void UpdateDB(QuoteDataSet dataSet, Strint tableName)
{
    using(SQLiteConnection conn = new SQLiteConnection(_connectionString))
    {
        conn.Open();
        using (SQLiteTransaction transaction = conn.BeginTransaction())
        {
            using (SQLiteCommand cmd = new SQLiteCommand("SELECT * FROM " + tableName, conn))
            {
                using (SQLiteDataAdapter sqliteAdapter = new SQLiteDataAdapter())
                {
                    sqliteAdapter.Update(dataSet, tableName);
                }
            }
            transaction.Commit();
        }
    }
}

Документация C # гласит, что с помощью оператора using объект внутри области будет удален, и я видел несколько мест, где предполагается, что нам не нужно использовать предложение try / finally.

Обычно я окружаю свои соединения попыткой / окончанием, и я всегда закрываю соединение в предложении окончательно. Учитывая приведенный выше код, разумно ли предположить, что соединение будет закрыто, если есть исключение?

Ответы [ 5 ]

19 голосов
/ 26 апреля 2010

Вы правы; оператор using компилируется в блок try / finally .

Компилятор преобразует using(resource) statement; в следующий код:

{
   ResourceType resource = expression;
   try {
      statement;
   }
   finally {
      if (resource != null) ((IDisposable)resource).Dispose();
   }
}

(приведение к IDisposable происходит в случае, если ResourceType реализует IDisposable явно.

10 голосов
/ 26 апреля 2010

Да, вам нужно использовать оператор try / finally или оператор using. Вам не нужны оба.

A с использованием оператора почти совпадает с оператором try / finally, за исключением того, что в C # 3 нельзя переназначить переменную внутри блока using.

using (IDisposable d = foo())
{
     d = null; // Error:  Cannot assign to 'd' because it is a 'using variable'
}

Ранее вы могли переназначать, но исходный объект все равно был бы удален, а не вновь назначенный объект, и вы также получили бы это предупреждение компиляции:

Возможно, неправильное присвоение локальному 'd', которое является аргументом оператора using или lock. Вызов или разблокировка Dispose будут выполняться на исходном локальном значении.

6 голосов
/ 26 апреля 2010

Да, оператор using - это просто сокращение для блока try ... finally.

Например, этот код ...

using (MyDisposableType foo = new MyDisposableType())
{
    foo.DoSomething();
}

... будет соответствовать следующему ...

{
    MyDisposableType foo = new MyDisposableType();
    try
    {
        foo.DoSomething();
    }
    finally
    {
        if (foo != null)
            ((IDisposable)foo).Dispose();
    }
}
1 голос
/ 26 апреля 2010

Использование () гарантирует, что элемент, созданный в параметрах, будет удален независимо от того, что происходит в связанном блоке кода.Это включает в себя закрытие соединения с базой данных при условии, что SQLiteConnection правильно обрабатывает его удаление.

1 голос
/ 26 апреля 2010

Вы можете предположить, что соединение будет закрыто, если вы получите исключение.

...