Класс, который наследует от базы, которая реализует IDisposable, обычно должен гарантировать, что вызов IDisposable.Dispose будет вызывать логику распоряжения базового класса, а также свою собственную.Для этого необходимо, чтобы было применено хотя бы одно из двух условий:
- Должны быть некоторые средства, с помощью которых производный класс может запросить, чтобы логика Dispose производного класса вызывалась из реализации базового класса IDisposable..Dispose (), без необходимости повторной реализации IDisposable.Dispose ().
- Если производный класс повторно реализует IDisposable.Dispose, должны быть какие-то средства, с помощью которых базовый класс может представить свою собственную удаленную логику производному классу, чтобы подпрограмма IDisposable.Dispose производного класса могла вызвать его.
Существует ряд способов, по которым хотя бы одно из этих условий может быть выполнено;в разных ситуациях разные методы могут быть оптимальными.В частности, для классов, имеющих открытый метод Dispose (), который будет семантически идентичен методу IDisposable.Dispose (), было бы проще всего просто иметь базовый класс открытым виртуальным методом Dispose (), который неявно реализует IDisposable.Dispose.Если производный класс переопределяет этот метод, он переопределяет поведение IDisposable.Dispose, но его Dispose () может вызывать base.Dispose () для активации логики удаления родительского объекта.Однако у этого подхода есть один недостаток: некоторые классы могут не захотеть иметь открытый метод Dispose (), который семантически идентичен IDisposable.Dispose ().Хотя было бы целесообразно использовать этот подход для классов, где он подходит, и какой-то другой подход для других классов, Microsoft решила, что было бы лучше иметь общий подход для всех классов.
Идея состоит в том, чтовсе наследуемые классы, которые реализуют IDisposable, будут иметь защищенный виртуальный метод, сигнатура которого не соответствует общедоступному «void Dispose ()»;IDisposable.Dispose () будет вызывать этот метод (со значением параметра True) для всей его логики удаления, а производный класс, который переопределяет этот метод, может вызывать базовую логику удаления, вызывая соответствующий метод его родителя.Хотя Microsoft допустила возможность метода «Завершить», вызывающего этот метод со значением false, на самом деле в этом нет никакой необходимости. Добавление метода Finalize (или деструктора C #) к классу, который не включает в себя все условия, требуемые для одного, включая вызовы GC.KeepAlive () в ключевых местах), может привести к поломкеизменение, которое вызывает незначительные ошибки. Если класс должен использовать неуправляемые ресурсы, но родительский класс этого не делает, это следует обработать, определив новые финализируемые классы для инкапсуляции неуправляемых ресурсов в управляемые объекты, а затем унаследованный класс будет содержать теуправляемые объекты.