честно говоря, до сих пор не понимаю, зачем в примере написали всю эту мешанину из флагов и параметров.
не советую внимать это и тем более использовать. юз-кейсов я пока не видел ни одного
вникать — потому что в MS библиотеках так и сделано освобождение ресурсов. И если вы наследуетесь от какого либо класса, который есть в стандартной библиотеке, то должны знать, как вам, как потомку, предполагается освобождать ресурсы.
>внимательный легко читатель найдет принципиальные ошибки в коде…
указание на ошибки только приветствуется — это же хорошо когда на них указывают. хуже когда про ошибки не говорят.
>… из-за которых использовать эту мега-идею не получится.
я сам предложенный класс мега-гениальным не считаю. он просто есть и он просто взят из msdn. вариантов его можно предложить разных и много. хуже, лучше — зависит от конкретной ситуации.
>при этом забыть вызвать base.Dispose(..) никто не мешает.
base.Dispose(...) таки забывают, согласен. иногда по забывчивости, а иногда — по не знанию.
>так что — имплементируйте IDisposable, пользуйтесь using, и всем будет хорошо.
С этим никто не спорит. Все верно.
Только я больше о другом: если тебе нужно наследовать от стандартного класса, например System.Windows.Forms.UserControl, то что в этом случае делать? Интерфейс IDisposable уже реализован в предке (на уровне System.ComponentModel.Component).
А очень хочется, чтобы твой контрол работал с unmanaged ресурсами. Например этот контрол должен уметь рендерить при помощи OpenGL и для этого ему надо уметь захватывать контекст устройства. И, соотвественно, уметь корректно его освобождать.
Перекрывать уже существующий метод Dispose — не вариант. И что тогда? Хотя про такое наследование у меня почти ничего и не написано… =(
Напишу следующий пост про наследование и Dispose =)
Но это уже не сегодня.
пару замечаний могу сказать сразу — то что в глаза бросилось. и это не связано напрямую со статьей
1. «private void Dispose(bool manual)»
должно быть virtual и скорее всего protected. без этого вся идея о наследовании становится бредом
2. private bool disposed = false;
я бы сделал protected. чтобы не делать ненужные копии в наследниках
3. //потому что в другом случае случае Dispose для них вызовет GC
касается вообще всего блока внутри «if (manual)»: смысла я не понял. потому что не понял с чего бы это коллектору вызывать какой-то там Dispose у каких-то managed ресурсов. и зачем делить на красных и белых? не диспознуто — диспозай. больше чем есть все равно не убить. если это может вызвать побочные эффекты — то лучше пусть вызывает. и чем больше и лучше — тем проще будет найти ошибки в архитектурных подходах
зы. а вот как раз var, я считаю, использовать корректно. я как бы за даже, потому что если F# продвинется, то пригодится.
зыы. ну минусуйте, подонки :) все равно правда восторжествует
2. да, давайте наплодим одних и тех же сущностей. к тому эе это могло бы стать частью контракта базового класса — раз уж от него предполагается наследоваться. get-only property я считаю лучше. и что значит не лезть, если мне предлагают именно с ней и ознакомится.
3. к сожалению, никакого «потому что» я там не увидел
>касается вообще всего блока внутри «if (manual)»: смысла я не понял. потому что не понял с чего бы это коллектору вызывать какой-то там Dispose у каких-то managed ресурсов. и зачем делить на красных и белых? не диспознуто — диспозай.
пример не придуман, а взят из мсдн. не то что бы мсдн — последняя инстанция, но как «пожелания от MS» пойдет. Я могу только предполагать, зачем было решено разделить освобождение managed и unmanaged ресурсов.
Скорее всего дело тут в следующем. Как только был вызван Dispose из кода программы (а не во время работы сборщика мусора) предполагается «полная и прямо сейчас» очистка всех unmanaged ресурсов. А они могут быть не только в самом классе, но и внутри его managed член-переменных. Ждать, когда для них вызовется GC — не вариант. Поэтому для managed переменных тоже предполагается вызов Dispose — чтобы они тоже могли освободить свои unmanaged ресурсы.
да, в онлайн msdn именно такой пример и приведен. плохо.
в голову легко приходит случай, когда component не будет освобожден, а никто не гарантирует, что у него нет unamanged ресурсов
кстати, ключевые моменты в статье, которой ссылался зойдберг: bad design и backward compatibility
Вот про GC.SuppressFinalize я не знал, спасибо.
Однако, мне очень сложно представить задачу, где так надо освобождать ресурсы, тк обычно используются уже готовые классы, в которых это всё уже реализовано.
очень хорошая статья — мне понравилось. никаких обид.
да я и не претендовал на новизну: сразу предупредил что речь всего лишь о пересказе известной информации. просто она, на мой взгляд, представляет некоторый интерес.
Объявляемые в области метода переменные могут иметь неявный тип var. Локальная переменная с неявным типом имеет строгую типизацию, как если бы тип был задан явно, только тип определяет компилятор.
Что то с этим GC еще внимательнее нужно программировать и лучше все его тонкости понимать чем на обычном C++. «Захотела MS самодельную JVM, налабала фуфла и навязывает его изовсех сил». Происходит тоже самое, что помоему было с ActiveX,OLE, COM — некоторые возможности лепятся сбоку и ими невозможно пользоваться (MFC, CLR C++, ...)
ИМХО в .NET с GC особых проблем не вижу, зачастую они появляются из-за кривых ручек… А вот IDisposable есть некоторые проблемы когда используешь unmanaged ресурсы, но они легко решаются когда знаешь правильный шаблон кода для таких ситуаций.
проставлять флаг disposed = true лучше перед основным кодом освобождения ресурсов, иначе может быть проблема с многопоточным кодом. а финалайзеры — особая тема, не всегда следует их реализовывать по нескольким причинам. во-первых, существуют классы, которые требуют детерминированного уничтожения (например, используют другие managed-ресурсы, которые должны быть освобождены). в этом случае финалайзер не будет выполнять полезной работы и будет только мешать, создавая иллюзию нормальной работы и замедляя работу приложения (финалайзеры требуют особого обращения со стороны среды выполнения CLR .NET). кстати, в таких случаях в финалайзер можно засунуть метод оповещения о том, что объект не был освобожден принудительно, таким образом сигнализируя об утечке памяти / ресурсов. и этим мы элегантно превращаем «плохой» финалайзер в «хороший» и полезный. подробнее об этом я тоже планирую написать отдельную статью.
//
а вообще, ничего, спасибо вам за труд.
О бедном Dispose замолвите слово