Dispose() для очистки управляемых ресурсов?

В этом ответе я нашел,

Очистите неуправляемые ресурсы в методе Finalize и управляемые в методе Dispose, если в вашем коде используется шаблон Dispose/Finalize.

А потом я нашел эту хорошую статью о доработке и утилизации и получил четкое представление о них. В статье есть следующий код (страница 3), чтобы объяснить концепции:

class Test : IDisposable
{
    private bool isDisposed = false;

    ~Test()
    {
       Dispose(false);
    }

    protected void Dispose(bool disposing)
    {
       if (disposing)
       {
          // Code to dispose the managed resources of the class
       }
       // Code to dispose the un-managed resources of the class

       isDisposed = true;
    }

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

Но ниже того же примечания (которое я включил в начало этого вопроса) появляется.

Шаблон Dispose/Finalize Microsoft рекомендует использовать как Dispose, так и Finalize при работе с неуправляемыми ресурсами. Тогда правильная последовательность будет для разработчика, чтобы вызвать Dispose. Реализация Finalize будет запущена, и ресурсы будут по-прежнему освобождаться, когда объект будет подвергаться сборке мусора, даже если разработчик не будет явно вызывать метод Dispose. Франческо Балена пишет в своем блоге: "Шаблон Dispose/Finalize следует использовать только в том случае, если ваш тип вызывает неуправляемый код, который выделяет неуправляемые ресурсы (включая неуправляемую память), и возвращает дескриптор, который вы должны использовать в конечном итоге для освобождения ресурса. связать их с родительскими объектами, вызывая соответствующие методы их родителей после того, как они утилизировали или завершили свои собственные члены ". Проще говоря, очистите неуправляемые ресурсы в методе Finalize и управляемые в методе Dispose, когда в вашем коде используется шаблон Dispose/Finalize.

Теперь я снова в замешательстве. Во всей статье и в примере кода показано, что неуправляемые ресурсы должны быть освобождены в Dispose(), Но тогда какова актуальность этого комментария?

Редактировать:

Как подтверждается, что эта строка:

Проще говоря, очистите неуправляемые ресурсы в методе Finalize и управляемые в методе Dispose, когда в вашем коде используется шаблон Dispose/Finalize.

Ошибочно, я редактировал этот ответ.

2 ответа

Решение

Вижу это очень просто.

  1. Если вы имеете дело с неуправляемыми ресурсами - реализуйте оба Dispose а также Finalize, Dispose должен вызывать разработчиков, чтобы освободить ресурсы, как только они увидят, что они им больше не нужны. Если они забывают позвонить Dispose затем Framework вызывает финализацию в своем собственном цикле GC (обычно это займет свое время).
  2. Если вы НЕ имеете дело с неуправляемыми ресурсами - тогда ничего не делайте. Не осуществлять Finalize ни Dispose,
  3. Если ваш объект использует одноразовые объекты внутри - вы реализуете Dispose() если вы создали и сохранили ссылку на любой объект типа, который реализует Dispose() и который вы еще не утилизировали.

Несколько классических примеров:

System.IO.FileStreamОбъект управляет дескрипторами блокировки / потока к файлам. Таким образом, он реализует как распоряжаться, так и завершать. Если разработчик располагает им, другая программа может получить к нему доступ сразу же. Если он забудет утилизировать его, то Framework завершит его и закроет дескрипторы позже в цикле GC.

System.Text.StringBuilder Доза не имеет никакого неуправляемого ресурса. Так что не распоряжаться, не доработать.

Что касается модели, что это значит для

// Code to dispose the managed resources of the class

это вызов метода Dispose любых объектов.NET, которые у вас есть в качестве компонентов внутри этого класса

А также

// Code to dispose the un-managed resources of the class

Средства для закрытия необработанных ручек и указателей. Вот ваш обновленный код с примерами

class Test : IDisposable
   {
     private bool isDisposed = false;

     ~Test()
     {
       Dispose(false);
     }

     protected void Dispose(bool disposing)
     {
       if (disposing)
       {
         // Code to dispose the managed resources of the class
         internalComponent1.Dispose();
         internalComponent2.Dispose();
       }

       // Code to dispose the un-managed resources of the class
       CloseHandle(handle);
       handle = IntPtr.Zero;   

       isDisposed = true;
     }

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

Вот старый вопрос, объясняющий это

Если Foo имеет ресурсы, которые выиграют от детерминированной очистки, но ни один из которых не может быть эффективно очищен в финализаторе, он должен реализовать IDisposable но не должен переопределять Finalize или есть деструктор. Если класс содержит несколько ресурсов, и хотя бы один из них может быть очищен в финализаторе, то каждый отдельный ресурс, который может быть очищен в финализаторе, должен быть инкапсулирован в свой собственный объект, оснащенный финализатором / деструктором (который может быть определен в защищенный вложенный класс), и класс, который будет содержать эти ресурсы, должен содержать ссылки на объекты-оболочки. Как только это будет сделано, внешний класс будет соответствовать шаблону для классов с Dispose метод, но не финализатор / деструктор.

Другие вопросы по тегам