Сколько работы нужно выполнить в методе Dispose?
Это зависит от того, реализуете ли вы интерфейс IDispose только для удобства использования оператора, или вы реализуете полный шаблон IDisposable? В последнем случае полного одноразового шаблона все еще допустимо выполнять более сложные действия при условии, что вы «утилизируете» параметр true (т.е. вы не в GC).
Когда вы определяете финализатор, который вызывает метод Dispose, на самом деле беспокоиться не о чем. Подобные случаи использования / злоупотребления интерфейсом IDisposable, о котором упоминалось, уже были другими (т.е. using (Html.BeginForm())
) способны выполнять любые действия. Зачастую это может значительно снизить сложность кода и предотвратить случайное забвение кодировщиками некоторых закрывающих действий. Один недостаток (или недостаток) заключается в том, что код выполняется немного по-другому внутри блока finally .
В конструкторах я всегда придерживался позиции, что вы должны делать только то, что абсолютно необходимо для создания экземпляра объекта.
Объекты, ИМХО, должны быть действительны после постройки. Так что если у вас есть много работы, чтобы сделать что-то, пусть будет так. Не думайте о рабочей нагрузке, думайте о потребителе вашего объекта и его удобстве использования. Методы Initialize () после построения suck;)
В этом случае я также всегда придерживался подхода, согласно которому вы должны ТОЛЬКО убирать открытые ресурсы при утилизации. Закрытие файлов, освобождение памяти, удаление одноразовых дочерних объектов и т. Д. Не следует выполнять длительные процессы, такие как касание файлов, доступ к базам данных и т. Д. В методе Dispose.
На самом деле давайте немного разберемся с этим ...
Удаление из вызова GC для финализатора
Когда вы реализуете шаблон IDisposable (не интерфейс, шаблон, финализатор и все), вы, по сути, говорите, что у вашего объекта есть неуправляемый ресурс, о котором никто больше не знает. Это означает, что вы вызвали вызов CreateFile в Win32, или, может быть, вы назвали Marshal.AllocHGlobal или что-то в этом роде. По сути, у вас, скорее всего, есть член экземпляра IntPtr, с которым нужно что-то делать, чтобы предотвратить утечку памяти. Это ЕДИНСТВЕННЫЕ типы действий, которые должны быть выполнены, когда параметр распоряжения имеет значение false (то есть вызывается из финализатора в потоке GC).
Как правило, вы НЕ вызываете метод Dispose для детей. Вы не должны ожидать, что любой дочерний объект будет действительным. Простое прикосновение к члену дочернего объекта может случайно «оживить» или воскресить его .
Поэтому, когда вы пишете код, который выполняется в методе Dispose, вызываемом из Finalizer, вы должны быть осторожны. Вы выполняете в потоке GC, пока остальная часть вашего приложения ждет вас. Вы должны выполнить как можно меньше операций, чтобы освободить неуправляемую память / ресурс и выйти. Никогда не создавайте исключение, и если вы вызываете API, который может выдать, вы должны перехватить любое возникшее исключение. Распространение исключений обратно в GC приведет к преждевременному прерыванию потока финализатора, и оставшиеся объекты, которые должны быть завершены, не смогут очиститься.
Удаление из метода IDisposable.Dispose ()
Как я уже говорил, использование метода Dispose является достаточно безопасным и может безопасно вместить любое количество кода / процесса. Здесь вы можете освободить неуправляемые ресурсы, вызвать метод dispose дочерних объектов, очистить и закрыть файлы и т. Д. Большинство написанных мной методов Dispose не имеют связанного Finalizer и, следовательно, не следуют шаблону IDisposable, однако они реализовать IDisposable только для удобства оператора using
.
Я не прав?Эти действия в порядке, если вы обрабатываете любые возможные исключения, чтобы они не выходили за пределы метода?Я просто не думаю, что делать много в Dispose - это хорошая идея.Я хотел бы знать, что думает сообщество.
Вы абсолютно правы, когда рассматриваемый метод dispose используется из финализатора.Ваши утверждения о том, что вы должны и чего не должны делать в методе Dispose, должны быть перефразированы для применения ко всему, что вызывается финализатором.Тот факт, что это обычно делается в методе, называемом Dispose, является условием, шаблоном IDisposable, но эти проблемы могут легко существовать в других методах, используемых Finalizer.