Должны ли реализации IDisposable.Dispose () быть идемпотентными? - PullRequest
21 голосов
/ 19 января 2012

Microsoft.NET Framework предоставляет интерфейс IDisposable, который требует реализации метода void Dispose().Его цель - разрешить ручное или объемное освобождение дорогих ресурсов, которые могла бы выделить реализация IDisposable.Примеры включают базы данных, потоки и дескрипторы.

Мой вопрос заключается в том, должна ли реализация метода Dispose() быть идемпотентной - при вызове более одного раза в одном и том же экземпляре экземпляр должен быть «удален» только один раз, а последующие вызовы не вызывают исключений,В Java большинство объектов, имеющих сходное поведение (опять-таки, в качестве примера, мне приходят в голову потоки и соединения с базой данных), являются идемпотентными для их операции close(), которая является аналогом для метода Dispose().

Однако мой личный опыт работы с .NET (и, в частности, Windows Forms) показывает, что не все реализации (которые являются частью самой платформы .NET ) являются идемпотентными, поэтому последующиевызовы этих бросают ObjectDisposedException.Это действительно смущает меня тем, как следует подходить к реализации одноразового объекта.Есть ли общий ответ для сценария или он зависит от конкретного контекста объекта и его использования?

Ответы [ 4 ]

19 голосов
/ 19 января 2012

если реализация метода Dispose() идемпотентна

Да, так и должно быть. Пока неизвестно, сколько раз он будет вызван.

С Реализация метода удаления в MSDN:

метод Dispose должен вызываться несколько раз без исключения.

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

7 голосов
/ 19 января 2012

Да, также убедитесь, что другие методы класса правильно реагируют, когда они вызываются, когда объект уже был удален.

public void SomeMethod()
{
     if(_disposed)
     {
         throw new ObjectDisposedException();
     }
     else
     {
         // ...
     }

}
5 голосов
/ 19 января 2012

От MSDN:

Разрешить вызов метода Dispose более одного раза без исключения. Метод не должен делать ничего после первого вызова.

3 голосов
/ 19 января 2012

Лично - Да - я всегда делаю идемпотентность Dispose ().

Во время обычного жизненного цикла объекта в данном приложении это может не понадобиться - жизненный стиль от создания до избавления может бытьдетерминированный и хорошо известный.

Однако, в равной степени, в некоторых приложениях это может быть не так ясно.

Например, в сценарии декоратора: у меня может быть одноразовый объект A, украшенный другим одноразовым объектом B. Я могу хотеть явно удалить A, и, тем не менее, Dispose на B может также удалить экземпляр, который он оборачивает (think: streams).

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...