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

Когда следует реализовать IDisposable?

Какова наилучшая практика для реализации IDisposable?

Лучшее эмпирическое правило для его реализации, если у вас есть один управляемый объект в классе или зависит от того, был ли объект создан в классе или просто прошел? Должен ли я также делать это для классов без управляемых объектов?

4b9b3361

Ответ 1

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

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

Ответ 2

В то время как все упомянули (неуправляемые) ресурсы, у меня есть еще одна вещь, которую нужно добавить: я использую ее, когда мне нужно устранить подключения обработчика событий, которые в противном случае не позволяли классу выйти из области видимости и собирать мусор.

В качестве примера у меня есть служба, которая вводится в дочернее представление, это дочернее представление будет подписываться на различные события типа асинхронного типа в службе. Владелец этого дочернего представления понятия не имеет, каков конкретный тип, он просто имеет его как интерфейс. Служба может выйти из сферы действия в какой-то произвольный момент в будущем, и я не хочу, чтобы она висела вокруг, не будучи GC'ed. После устранения этого дочернего представления владелец вызовет Dispose на нем, чтобы дать ему возможность отцепить обработчики событий. Вот немного надуманный (и очень псевдокод) пример, обратите внимание, как интерфейс для дочернего представления также реализует IDisposable.

public class OwnerView {

    public OwnerView() {
        _childView = new ChildView(myServiceReference);
    }

    public void CloseChildView() {
        if (childView != null) {
            _childView.Close();
            _childView.Dispose();
        }

        _childView = null;
    }

    private IChildView _childView;
}

public class ChildView : IChildView {

    public ChildView(MyService serviceRef) {
        _serviceRef = serviceRef;
        _serviceRef.GetSettingsAsyncFinished += new EventHandler(someEventHandler);
    }

    public void IDisposable.Dispose() {
        _serviceRef -= someEventHandler;
    }

    private MyService _serviceRef;
}

public interface IChildView : IDisposable {
    void DoSomething();
    ... etc ...
}

Есть более достоверные комментарии об этом от других на SO, например Обработчики событий перестают собирать сборку мусора? и Сбор мусора при использовании анонимных делегатов для обработки событий. Вы также можете проверить эту статью codeproject.

Ответ 3

Вы должны реализовать IDisposable, когда ваш класс содержит ресурсы, которые вы хотите разблокировать, когда вы закончите использовать их.

Ответ 4

Когда ваш класс содержит неуправляемые объекты, ресурсы, открытые файлы или объекты базы данных, вам необходимо реализовать IDisposable.

Ответ 5

Я думаю, документы довольно ясно о том, для чего подходит IDisposable.

Основное использование этого интерфейса для освобождения неуправляемых ресурсов. сборщик мусора автоматически освобождает память, выделенную управляемый объект, если этот объект отсутствует дольше используется. Однако это не можно предсказать, когда мусор будет происходить сбор. Более того, сборщик мусора не знает неуправляемых ресурсов, таких как окно ручками или открытыми файлами и потоками.

У него даже есть пример. В этом примере класс, реализующий IDisposable, содержит дескриптор. Ручка должна быть освобождена, когда она больше не используется. Это делается в методе Dispose(). Таким образом, пользователь этого класса видит, что он реализует IDisposable и знает, что класс должен быть явно удален, когда он больше не нужен (поэтому дескриптор может быть освобожден). Это наилучшая практика (например, правило), что вы всегда должны вызывать Dispose() в IDisosable экземплярах, когда экземпляр больше не нужен.

Ответ 6

Если у него есть свойства, которые также должны быть удалены.