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

Какой смысл переопределять Dispose (bool disposing) в .NET?

Если я напишу класс в С#, который реализует IDisposable, почему этого недостаточно, я просто реализую

public void Dispose(){ ... } 

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

Есть

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

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

4b9b3361

Ответ 1

Это не обязательно. Это часть рекомендуемого одноразового шаблона. Если вы не прочитали раздел "Руководства по дизайну рамок" (9.3 в первом издании, не имеете второго варианта, извините), то вам следует. Попробуйте эту ссылку.

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

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

Ответ 2

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

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

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

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

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

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

Ответ 3

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

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

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

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

Ответ 5

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

Ответ 6

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

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

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

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

Ответ 7

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

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

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

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

Ответ 8

Если класс реализует 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), требуют, чтобы производные классы обрабатывали свою логику очистки способом, который отличается от соглашения. Некоторые языки, такие как С++/CLI, которые предназначены только для расширения реализаций IDisposable, которые следуют этому соглашению, могут быть неспособны выводить классы из нестандартных реализаций.