Подтвердить что ты не робот

Является ли IDisposable.Dispose() автоматически вызванным?

Возможный дубликат:
Будет ли вызов сборщика мусора IDisposable.Dispose для меня?

У меня есть класс, у которого есть неуправляемые ресурсы. Мой класс реализует интерфейс IDisposable и освобождает неуправляемые ресурсы в методе Dispose(). Должен ли я вызвать метод Dispose() или он будет автоматически вызван каким-то образом? Позвонит ли это сборщик мусора?

4b9b3361

Ответ 1

Dispose() не будет вызываться автоматически. Если есть финализатор, он будет вызываться автоматически. Реализация IDisposable позволяет пользователям своего класса рано выпускать ресурсы, а не ждать сборщика мусора.

Предпочтительным способом для клиента является использование оператора using, который обрабатывает автоматический вызов Dispose(), даже если есть исключения.

Правильная реализация IDisposable такова:

class MyClass : IDisposable
{
  private bool disposed = false;

  void Dispose() 
  { 
    Dispose(true); 
    GC.SuppressFinalize(this);
  }

  protected virtual void Dispose(bool disposing)
  {
    if(!disposed)
    {
      if(disposing)
      {
        // Manual release of managed resources.
      }
      // Release unmanaged resources.
      disposed = true;
    }
  }

  ~MyClass() { Dispose(false); }
}

Если пользователь класса вызывает Dispose(), очистка происходит непосредственно. Если объект улавливается сборщиком мусора, он вызывает Dispose(false) для очистки. Обратите внимание, что при вызове из финализатора (метод ~MyClass) управляемые ссылки могут быть недопустимыми, поэтому можно освободить только неуправляемые ресурсы.

Ответ 2

Чтобы убедиться, что ресурсы правильно расположены, вам необходимо реализовать IDisposable и вызвать Dispose в деструкторе (финализатор).

class Foo : IDisposable
{
    private bool m_disposed = false;

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    ~Foo()
    {
        Dispose(false);
    }

    protected void Dispose(bool disposing)
    {
        if (!m_disposed)
        {
            if (disposing)
            { 
                //release managed resources
            }
            //release unmanaged resources

            m_disposed = true;
        }
    }
}

Ответ 3

Если вы создаете экземпляр объекта в инструкции using, Dispose() вызывается для вас, когда код выходит из блока using

using(var myObject = new MyDisposableObject())
{
  blah();
} // Dispose() is called here (or whenever the code exits the block)

Если вы не используете using, то вам (код вызова) удалять свой объект, явно вызывая Dispose().

Кроме того, вы (разработчик MyObject) можете добавить поддержку финализатора в случае, если ваш вызывающий абонент не вызывает Dispose(). Подробнее здесь.

Ответ 4

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

using(var myclass = new MyClass())
{
   // do something with myclass
}

// now 'myclass'is Disposed