Поскольку в Интернете доступны сотни статей, мне нужно упомянуть причину, по которой я написал что-то на ту же тему. Мы знаем механизм сборки мусора, мы знаем IDisposable и знаем, как использовать ключевое слово. Итак, давайте ответим на несколько вопросов, прежде чем мы начнем читать статью.

  1. Если возникает исключение из кода в блоке Using, удаляется ли объект по-прежнему?
  2. Если деструктор может позаботиться об удалении неуправляемых объектов, зачем нам метод Dispose?
  3. Могу ли я использовать блок «Использование» в любом классе или есть ли какие-то предварительные условия?

Если вы хотите найти ответы на эти вопросы, давайте читать дальше.

Прежде чем мы перейдем к IDisposable, сначала отметим некоторые моменты, касающиеся сборщика мусора.

  1. GC - ключевая особенность .Net framework, в которой программисту не нужно заботиться об утилизации использованных объектов, чтобы освободить память для дальнейшей работы. Об этом позаботится Framework.
  2. Каждое приложение, которое мы запускаем, имеет стек и кучу памяти. Память кучи, которая используется для хранения объектов, разделена на три версии - 0,1,2. В стековой памяти хранится таблица soft-link, в которой хранится связь объектов друг с другом.
  3. Для каждой версии существует отдельный поток GC. В начале нет объекта в версии 1 или 2. Если объекты сохраняются в операции сборки мусора версии 0, они повышаются до версии 1.
  4. Поток GC запускается через определенный интервал или всякий раз, когда не хватает памяти. Интервал указывается в миллисекундах. Каждый запуск состоит из трех этапов - MCC (Mark, Collect, Compact).
  5. Начните с корня - ›Используя таблицу софт-ссылок, рекурсивно отметьте все используемые объекты -› Затем соберите адреса объектов, на которые больше не ссылаются - ›Начните использовать память таких бесхозных объектов, чтобы сжать существующие объекты и обновить таблица софт-ссылок с новыми адресами.

Управляемый и неуправляемый код

Любой компонент, о котором знает .Net framework (чтобы он мог управлять созданием и удалением), называется управляемым кодом. Существуют определенные компоненты, которые выходят за рамки .Net framework, например. подключение к базе данных, обработчики файлов или любой компонент, написанный на языке, который .NET Framework не может понять. Сборка мусора может автоматически удалить управляемый код, но не может освободить неуправляемый код, так как не может отслеживать, требуется ли удаление объекта или все еще используется.

IDisposable

Поскольку .Net framework не может определить, когда избавиться от неуправляемого кода, нам необходимо явно послать сигнал Dispose для таких объектов. Для этого мы используем интерфейс IDisposable.

В приведенном выше коде нам нужен файловый поток (поток ввода-вывода, который позволяет нам читать / писать в файл). Это неуправляемый компонент. Чтобы избавиться от этого, нам нужно реализовать интерфейс IDisposable, написать код утилизации в методе Dispose (), и все готово !! Поэтому всякий раз, когда метод Dispose () вызывается в FileHandlerDemo, он вызывает то же самое для FileHandle.

Можем ли мы написать такой же код в деструкторе?

да.

Это будет работать?

да.

Тогда зачем нам метод Dispose?

Чтобы понять это, нам нужно понять работу GC. Сборщик мусора обязан вызвать деструктор для любого объекта при его удалении. Разработчик не может контролировать, когда следует вызывать деструктор. Поэтому, если деструктор удаляет неуправляемый код, нам нужно дождаться, пока GC вызовет деструктор. В случае метода Dispose () пользователь должен явно вызвать этот метод, поэтому после завершения работы пользователь может вызвать метод и удалить дескрипторы.

Во-вторых, перенос объектов из версии 0 в версию 1 обходится дорого, если на объект нет ссылки. Когда GC пытается избавиться от любого объекта, на который нет ссылки, если у объекта есть деструктор, GC должен скопировать его из текущей версии в следующую, а затем вызвать деструктор. Это добавляет накладные расходы на сборщик мусора.

Вот почему нам нужна реализация IDisposable. Здесь следует отметить, что IDisposable должен быть реализован только в классах, использующих неуправляемый код.

Использование ключевого слова -

Часто мы наблюдаем неуправляемый код, написанный в блоке Using

Это означает, что объект, который используется в блоке Using, удаляется сразу после выхода элемента управления из блока Using. Итак, в основном мы вызываем метод Dispose для объекта fileHandle в конце блока using. Вот и все!!

Однако что, если исключение возникло из кода внутри блока using?

Чтобы понять, что произойдет, давайте посмотрим, как блок using действительно преобразуется в код.

Думаю, мне не нужно объяснять, что произойдет. Команда try-catch-finally заботится о плавном выполнении блока using.

Примечание. Управление памятью действительно потрясающее в мире .Net. Нам просто нужно эффективно позаботиться о неуправляемом коде.