RAII. Получение ресурса - это инициализация

Представим себе такую ситуацию:
var db = new DummyDb("server", "user", "password");
try
{
    db.EvalQuery("drop table sometable"); // точка "А"
    db.Disconnect();
}
catch(DbQueryException e)
{
    Log("cannot execute query");
}
Недостаток такого кода в том, что если возникнет исключительная ситуация в точке "А", то последующая команда не выполнится и, соответственно, соединение с сервером базы данных не будет разорвано.
Попробуем исправить такую ситуацию:
var db = new DummyDb("server", "user", "password");
try
{
    db.EvalQuery("drop table sometable");
}
catch(DbQueryException e)
{
    Log("cannot execute query");
}
finally
{
    db.Disconnect();
}
Блок finally гарантирует нам, что после выполнения try-блока будет выполнен код отключения от сервера БД в независимости от того, возникла исключительная ситуация или нет.

Подобная последовательность действий:
  • получение ресурса ("соединение с сервером БД" в нашем случае) и создание объекта соответствующего класса (DummyDb в нашем случае);
  • работа с ресурсом;
  • освобождение ресурса (разрыв соединения с сервером в нашем случае) и удаление объекта
достаточна типична.

Однако в управляемой среде прямое удаление объекта невозможно. И освобождение ресурса должно сопровождаться вызовом метода Dispose, объявленного в интерфейсе IDisposable. Использование оператора using позволяет сделать это автоматически:
var db = new DummyDb("server", "user", "password");
using(db))
{
    try
    {
        db.EvalQuery("drop table sometable");
    }
    catch(DbQueryException e)
    {
        Log("cannot execute query");
    }
} // после закрытия блока using автоматически будет вызван метод Dispose объекта db
Теперь код освобождения ресурса необходимо поместить в реализацию метода Dispose:
class DummyDB : IDisposable
{
    // ...
    public void Dispose()
    {
        // проверка необходима для безопасного повторного вызовы метода Dispose
        if(_isConnected) 
        {
            this.Disconnect();
        }
    }
    // ...
}

Last edited Mar 26, 2012 at 7:39 AM by basph, version 4

Comments

No comments yet.