2009-02-25 4 views
37

Если я пишу класс в C#, который реализует IDisposable, почему не достаточно для меня, чтобы просто реализоватьКакой смысл переопределять Dispose (bool disposing) в .NET?

public void Dispose(){ ... } 

для обработки освобождения любых неуправляемых ресурсов?

Является

protected virtual void Dispose(bool disposing){ ... } 

всегда необходимо, иногда необходимо, или что-то совсем другое?

+0

В моем классе у меня есть только неуправляемые ресурсы, которые нуждаются в очистке, и я реализую IDisposable с защищенным виртуальным void Dispose (bool disposing), который заставляет его выполнять статический анализ. В моем случае параметр «disposing» не имеет смысла, поскольку я бы хотел, чтобы Finalizer и Dispose выполняли то же самое. – AksharRoop

ответ

28

Не обязательно. Это часть рекомендуемого одноразового шаблона. Если вы не прочитали раздел «Руководства по дизайну рамок» (9.3 в первом издании, не имеете второго варианта, извините), то вам следует. Try this link.

Полезно для различения одноразовой очистки и финализируемой мусорной коллекции-is-trashing-me.

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

+3

Ссылка на «IDisposable: Что ваша мать никогда не говорила вам об освобождении ресурсов» слишком далеко внизу, поэтому я буду дублировать ее здесь: http://www.codeproject.com/KB/dotnet/IDisposable.aspx –

+0

FYI the первая ссылка выше на bluebytesoftware теперь сломана. – codenheim

+0

@mrjoltcola благодарит, обновляется до ссылки MSDN (но они могут быть немного эфемерными тоже) –

3

Дополнительный метод с утилизацией bool из-за чего-то из направляющей конструкции каркаса. Это просто шаблон, позволяющий вашему классу иметь способ удаления, который можно вызвать несколько раз, не выбрасывая исключение. Это не совсем необходимо. Технически вы можете сделать это в методе dispose.

13

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

  1. У вас есть поля такого типа, который реализует IDisposable
  2. У вас есть финализации.

Корпус 1 довольно распространен в большинстве кодов. Случай 2 довольно распространен в коде, который пишет Microsoft, это те, которые написали управляемые обертки вокруг неуправляемых ресурсов, те, которые требуют финализации. Но в вашем коде должно быть очень редко. В конце концов, у вас есть все те классные классы .NET, которые делают для вас грязную работу. Вам просто нужно вызвать методы Dispose().

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

+0

В моем классе у меня есть только неуправляемые ресурсы, которые нуждаются в очистке, и я реализую IDisposable с защищенным виртуальным void Dispose (bool disposing) в качестве статического анализ заставляет его делать. В моем случае параметр «disposing» не имеет смысла, поскольку я бы хотел, чтобы Finalizer и Dispose выполняли то же самое. – AksharRoop

+0

Не уверен, что этот комментарий предназначен для передачи. Вероятно, вы ошибаетесь, используйте классы оболочки SafeHandle и/или SafeBuffer. Критические финализаторы хороши. Назад к bullet 1. –

+0

Итак, мой первоначальный вопрос - это то, что должен делать другой Dispose (bool disposing), когда значение истинно, а значение - false. Для чего используется параметр утилизации? – AksharRoop

41

Полный шаблон, включающий финализатор, введение нового виртуального метода и «запечатывание» исходного метода размещения, является очень общим назначением, охватывающим все базы.

Если у вас нет прямые ручки на неуправляемых ресурсов (которые должны быть almostnever) вам не нужны финализации.

Если вы запечатываете свой класс (и мои взгляды на классы герметизации, где это возможно, вероятно, хорошо известны к настоящему времени - design for inheritance or prohibit it), нет смысла вводить виртуальный метод.

Не могу вспомнить последний раз, когда я осуществил IDisposable в «сложном» способе, и сделал это наиболее очевидным образом, например.

public void Dispose() 
{ 
    somethingElse.Dispose(); 
} 

Единственное, что следует отметить, что если вы собираетесь действительно надежный код, вы должны убедитесь, что вы не пытаетесь сделать что-либо после того, как вы избавились, и бросить ObjectDisposedException где это уместно , Это хороший совет для библиотек классов, которые будут использоваться разработчиками по всему миру, но это очень большая работа для получения очень небольшого выигрыша, если это будет только класс, используемый в вашем собственном рабочем пространстве.

+0

Удивительное объяснение - и облегчение! –

+0

FYI, ваша ссылка на bluebyte сломана –

+0

@HamishSmith: Исправлено, спасибо. (Блог переместился.) –

5

В дополнение к другим большим ответам, вы можете проверить эти статьи:

+2

Первая статья по-прежнему включает свойство «распоряжаться» в простом делете, что бессмысленно. Действительно простой случай - это то, что Джон поставил в своем примере, с возможным добавлением ключевого слова «virtual». – piers7

1

Просто расширить на то, что другие сказал: дело не только в том, что вам не нужно нужно «сложное распоряжение», это то, что вы на самом деле не хотят этого, для производительности rea сыновья.

Если вы идете по пути «сложного распоряжения» и реализуете финализатор, а затем забываете явно распоряжаться своим объектом, ваш объект (и все, что он ссылается) выдержит дополнительное генерация GC, прежде чем он будет действительно удален (поскольку он имеет еще раз обернуться, чтобы CLR вызывал финализатор). Это просто вызывает большее давление памяти, которое вам не нужно. Кроме того, вызов финализатора на целую кучу объектов имеет нетривиальную стоимость.

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

О, и пока мы находимся в этом районе: методы вашего класса, которые обрабатывают события от других, должны быть «безопасными» перед вызовом после того, как ваш класс был удален. Проще всего просто выполнить no-op, если класс расположен. См. http://blogs.msdn.com/ericlippert/archive/2009/04/29/events-and-races.aspx

1

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

Выполнение ничего управляемому объекту, отличному от «себя» в финализаторе, крайне ... непредсказуемо. Большинство из этого объясняется тем, что ваши финализаторы будут вызываться в стадии 2 завершения вашего AppDomain в недетерминированном режиме - поэтому, когда вы вызываете ваш финализатор, очень вероятно, что объекты, на которые вы все еще ссылаетесь, уже были завершена.

Dispatching вызовы Dispose и finalizer к тому же методу позволяют вам делиться вашим кодом выключения, в то время как логический параметр позволяет пропустить управляемую очистку, если она у вас есть.

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

1

Если класс реализует IDisposable.Dispose(), а производному классу необходимо добавить дополнительную логику, этот класс должен выставить какой-то метод Dispose, к которому может быть привязан производный класс. Поскольку некоторые классы могут реализовывать IDisposable.Dispose() без использования общедоступного метода Dispose(), полезно иметь виртуальный метод, который будет protected во всех реализациях IDisposable независимо от того, существует ли у них общедоступный метод Dispose.В большинстве случаев аргумент bool не имеет особого значения, но его следует рассматривать как фиктивный аргумент, чтобы сделать protected virtual Dispose(bool) другой подписью от may-be-or-maybe-not-public Dispose().

Классы, которые не используют protected virtual Dispose(bool), требуют, чтобы производные классы обрабатывали свою логику очистки способом, который отличается от соглашения. Некоторые языки, такие как C++/CLI, которые предназначены только для расширения реализации, которые следуют этому соглашению, могут быть неспособны выводить классы из нестандартных реализаций.

Смежные вопросы