Использует ли оператор С# выполнение try/finally?
Предположим, что у меня есть следующий код:
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();
}
}
}
В документации на С# указано, что с помощью оператора using
объект в пределах области будет удален, и я видел несколько мест, где он предположил, что нам не нужно использовать предложение try/finally.
Я обычно окружаю свои связи с помощью try/finally, и я всегда закрываю соединение в предложении finally. Учитывая приведенный выше код, разумно ли предположить, что соединение будет закрыто, если есть исключение?
Ответы
Ответ 1
Вы правы; оператор using
компилируется в блок try
/finally
.
Компилятор преобразует using(resource) statement;
в следующий код:
{
ResourceType resource = expression;
try {
statement;
}
finally {
if (resource != null) ((IDisposable)resource).Dispose();
}
}
(Приведение в IDisposable
в том случае, если ResourceType
явно реализует IDisposable
.
Ответ 2
Да, вам либо нужно использовать оператор try/finally или using. Вам не нужны оба.
A using statement почти то же самое, что и try/finally, за исключением того, что в С# 3 вы не можете переназначить переменную внутри использования блок.
using (IDisposable d = foo())
{
d = null; // Error: Cannot assign to 'd' because it is a 'using variable'
}
Раньше вы могли переназначать, но исходный объект все равно был бы удален, а не только назначенный объект, и вы также получили бы это предупреждение компиляции:
Возможно, некорректное присвоение локальному 'd', который является аргументом для оператора use или lock. Вызов Dispose или разблокировка произойдет при исходном значении локального.
Ответ 3
Да, оператор using
в значительной степени просто сокращает блок try ... finally
.
Например, этот код...
using (MyDisposableType foo = new MyDisposableType())
{
foo.DoSomething();
}
... приравнивается к следующему...
{
MyDisposableType foo = new MyDisposableType();
try
{
foo.DoSomething();
}
finally
{
if (foo != null)
((IDisposable)foo).Dispose();
}
}
Ответ 4
Можно предположить, что соединение будет закрыто, если вы получите исключение.
Ответ 5
Использование() гарантирует, что элемент, созданный в пределах параметров, будет удален независимо от того, что происходит в соответствующем кодовом блоке. Это включает в себя закрытие соединения с базой данных, предполагая, что SQLiteConnection
корректно обрабатывает его.