Реализация интерфейса IDisposable на c#

Когда-то давно я разобрался в и так несложном интерфейсе IDisposable и сделал "правильный" пример реализации, по сути, просто откомментировав код с MSDN, для лучшего понимания, зачем и почему нужно делать именно так:
class DisposableExample: IDisposable {
        #region Абсолютный минимум кода, который должен быть написан в правильной реализации IDisposable
        /// 
        /// Поле, где будет true, если объект уже пытались уничтожить.
        /// 
        private bool isDisposed = false;

        /// 
        /// Этот метод реализует интерфейс IDisposable.
        /// Он либо вызывается программистом явно, либо неявно - из блока using()
        /// Microsoft нам говорит, что этот метод не надо делать виртуальным, но не говорит, почему.
        /// Скорее всего, просто чтоб не нарушился порядок вызова Dispose()/GC.SuppressFinalize().
        /// 
        public void Dispose() {
            //Вызовем оверлоад метода и скажем, что его вызвали явно:
            Dispose(true);
            //Отменим вызов деструктора для этого объекта - всё, что нужно, мы уже за собой убрали.
            //Это не критично (поскольку у нас есть защита от повторного вызова метода Dispose(bool) - флаг isDisposed),
            //но поможет нам оптимизировать производительность.
            GC.SuppressFinalize(this);
        }

        /// 
        /// Это деструктор, он же finalizer.
        /// Его вызывает Garbage Collector, когда фреймворк соизволит решить, что пора бы убраться.
        /// 
        ~DisposableExample() {
            //Вызываем метод очистки, указывая, что он вызван из деструктора.
            //Если unmanaged ресурсов у нас нет, то тут "как бы" ничего нового не случится
            //и особого сакрального смысла в этом вызове нет, но лучше перебдеть, чем недобдеть.
            //Сюда мы придём только в том случае, если программист забыл уничтожить объект и не вызвал Dispose()
            Dispose(false);
            //Ничего больше в деструкторе быть не должно - весь код очистки ресурсов должен переехать в Dispose(bool)
        }

        /// 
        /// Очистка ресурсов.
        /// Чтобы не нарушить стройность логики в наследниках, этот метод не виртуальный, 
        /// виртуальными сделаны два метода DisposeManaged() и DisposeUnmanaged(), которые вызываются внутри.
        /// 
        /// 
        /// True, если метод Dispose() вызывается явно, либо из блока using()
        /// False, когда метод Dispose() вызывается из деструктора (неявно, при сборке мусора). Нельзя обращаться к Managed-ресурсам, о них позаботится Garbage Collector
        /// В примере из MSDN параметр назван "disposing", что совершенно не проясняет его предназначение.
        /// 
        protected void Dispose(bool isCalledExplicitly) {
            //Проверяем, что метод пока не вызывался:
            if(!isDisposed) {
                try {
                    if(isCalledExplicitly) {
                        //Dispose() был вызван явно программистом,
                        //он хотел освободить память, поскольку этот объект уже не понадобится.
                        //Garbage Collector до нашего объекта ещё не добрался, 
                        //поэтому мы сами освобождаем managed-ресурсы.
                        DisposeManaged();
                    }
                    //Освобождаем unmanaged-ресурсы, о них Garbage Collector-у никто не даст знать,
                    //поэтому кроме нас их никто не освободит
                    DisposeUnmanaged();
                } finally {
                    //Избегаем повторного вызова этого метода:
                    isDisposed = true;
                }
            }
        }

        /// 
        /// Освобождение внутренних managed-объектов.
        /// Может быть перекрыт в наследниках с вызовом base.DisposeManaged()
        /// Если делается базовый класс, без наполнения метода функциональностью,
        /// то метод должен быть не protected, а abstract.
        /// 
        protected virtual void DisposeManaged() {
            //Здесь надо уничтожить все managed-ресурсы
            //Все внутренние свойства, реализующие IDisposable, обрабатываются в этом методе:
            //this.DisposableProperty.Dispose();
        }

        /// 
        /// Освобождение внутренних unmanaged-ресурсов
        /// Может быть перекрыт в наследниках с вызовом base.DisposeUnmanaged()
        /// Если делается базовый класс, без наполнения метода функциональностью,
        /// то метод должен быть не protected, а abstract.
        /// 
        protected virtual void DisposeUnmanaged() {
            //Здесь очищаются ресурсы, о которых .Net Framework не знает,
            //например, открытые file handles:
            //CloseHandle(handle);
        }

        #endregion

        #region Дополнительные свойства и методы, которые могут пригодиться

        /// 
        /// Вернёт true, если объект уже уничтожен.
        /// Говорит о том, что этим объектом уже пользоваться не нужно.
        /// 
        protected bool IsDisposed { get { return isDisposed; } }

        /// 
        /// Метод выбросит эксепшн, если у объекта был вызван метод Dispose().
        /// CheckDisposed можно вставлять первой строкой в другие методы, 
        /// которым важна целостность объекта.
        /// 
        protected void CheckDisposed() {
            if(IsDisposed) throw new ObjectDisposedException(null);
        }

        #endregion
    }
Оценка: