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

Должны ли idisposable.Dispose() реализации быть идемпотентными?

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

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

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

4b9b3361

Ответ 1

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

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

От Внедрение метода удаления в MSDN:

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

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

Ответ 2

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

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

}

Ответ 3

Из MSDN:

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

Ответ 4

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

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

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

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

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