шаблон для освобождения объектов на управляемом языке - PullRequest
0 голосов
/ 06 января 2011

В сложном приложении (включающем инверсию управления и довольно много классов) вряд ли возможно узнать, когда на определенный объект больше не будут ссылаться.

Первый вопрос. Предлагает приведенное выше утверждение о том, что в таком приложении есть недостаток дизайна, поскольку существует шаблон, говорящий: «Во всех ОО-программах речь идет об объектах, использующих другие типы объектов, чтобы упростить реализацию. Однако: Для любой созданный объект должен иметь владельца, который позаботится о его сроке жизни. "

Полагаю, можно утверждать, что традиционное неуправляемое ОО-программирование работает, как указано выше: некоторые владельцы в конечном итоге освободят / освободят используемый объект.

Однако преимущество управляемого языка в том, что в принципе вам больше не нужно заботиться об управлении жизненным циклом. До тех пор, пока на объект ссылаются так или иначе (обработчик события ...) и из любого места (может быть, не «владелец»), он живет и должен жить, поскольку он все еще используется.

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

IStoppable : предложение шаблона проектирования Может существовать такой интерфейс, как «IStoppable», с методом «Stop ()» и событием «Stopped», чтобы любой другой объект, использующий его, мог удалить свои ссылки на объект. (Поэтому необходимо отключить их обработчик события OnStopped в обработчике события, если это возможно). В результате объект больше не нужен и будет собран.

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

Я думаю, что этот шаблон можно рассматривать как анархистский дизайн приложения, поскольку

  • это основано на идее, что ЛЮБОЙ другой объект может управлять временем жизни IStoppable
  • владелец не нужен
  • было бы нормально оставить решение об отмене регистрации в IStoppable тем, кто его использует
  • вам не нужно выбрасывать, уничтожать или выбрасывать - вы просто останавливаетесь и оставляете в живых (пусть GC сделает грязную часть)

IDisposable : из скетча и просто для проверки соответствующего шаблона: Одноразовый шаблон предполагает, что вы все равно должны думать и работать как в неуправляемом ОО-программировании: избавьтесь от объекта, который вам больше не нужен.

  • с использованием ваш друг в методе (очень удобно!)
  • в противном случае - ваш собственный IDisposable реализация.
  • после его использования / вызова Dispose вы не должны вызывать его больше: неопределенное поведение.
  • реализация и ориентированность на ресурсы: речь идет не столько о том, когда и почему, сколько о деталях восстановления ресурсов

Итак, еще раз: в приложении, где я не имею в виду, если что-то, кроме «владельца», указывает на объект, трудно гарантировать, что никто не будет ссылаться на него и называть его больше.

Я прочитал о событии «Утилизация» в классе Component .NET. Есть ли вокруг него шаблон дизайна?

Почему я хотел бы думать с точки зрения одноразовых изделий? Почему я должен? В управляемом мире ...

Спасибо! Себастьян

Ответы [ 4 ]

3 голосов
/ 06 января 2011

Мне лично не нравится идея IStoppable, как определено выше.Вы говорите, что хотите, чтобы любой объект управлял временем жизни объекта - однако определенный жизненный цикл действительно предполагает владение - разрешение нескольким объектам управлять временем жизни одного объекта в долгосрочной перспективе вызовет проблемы

Однако IDisposable - это хорошо определенный шаблон в мире .NET.Я написал целую серию по реализации IDisposable , которая представляет собой достойное введение в его использование.Однако он предназначен для обработки ресурса, который имеет неуправляемый компонент - когда у вас есть управляемый объект, который ссылается на собственный ресурс, часто желательно иметь явный контроль времени жизни этого ресурса.IDisposable - это определенный шаблон для обработки этой ситуации.

При этом надлежащая реализация IDisposable все равно очистит ваши ресурсы, если вы не вызовете Dispose().Недостатком является то, что ресурс будет очищен во время завершения объекта, что может произойти в любой произвольный момент после того, как объект больше не используется.Это может быть очень плохо по нескольким причинам - особенно если вы используете собственные ресурсы, которые по своей природе ограничены.Не утилизируя ресурс немедленно, вы можете исчерпать ресурсы до того, как GC запустится на объекте, особенно если в системе не слишком много нагрузки на память.

1 голос
/ 06 января 2011

Я думаю, что вы неправильно понимаете современные ОО языки;в частности область действия и сборка мусора.

Время жизни объектов в значительной степени определяется их областью действия.Ограничена ли область действия выражением using, методом или даже доменом приложения.

Хотя вам не обязательно «заботиться» о времени жизни объекта, компилятор делает это и отложит его для сборки мусора, как только он выйдет из области видимости.

Вы можете ускорить этот процесс, преднамеренно приказав сборщику мусора запускаться сейчас, но обычно это бессмысленное упражнение, поскольку компилятор в любом случае оптимизирует код, чтобы сделать это в самое подходящее время.* Если вы говорите об объектах в многопоточных приложениях, они уже предоставляют механизмы, чтобы остановить их выполнение или иным образом уничтожить их по требованию.

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

1 голос
/ 06 января 2011

Хорошо, сначала я хотел бы указать на некоторые вещи, которые мне не нравятся в вашем предложении IStoppable.

  1. Событие IStoppable вызывает Остановлено, потребители должны знать об этом и опубликовать ссылки.Это немного сложно в лучшем случае, проблематично в худшем.Потребители должны знать, где находится каждая ссылка, чтобы удалить / сбросить ссылку.

  2. Вы заявляете: «... Ничего не сломалось, просто удалив на него большинство ссылок».Это полностью зависит от объекта, реализующего IStoppable, и его использования.Скажем, например, мой объект IStoppable является кешем объектов.Теперь я забываю об этом событии или игнорирую его, и вдруг я использую другой кэш объектов, как и весь остальной мир ... может быть, это нормально, а может и нет.

  3. Событияужасный способ обеспечить такое поведение из-за того, что с исключениями оказывается трудно справиться.Что это значит, когда третий из 10 обработчиков событий вызывает исключение в событии IStoppable.Stopped?

Я думаю, что вы пытаетесь выразить объект, который может «принадлежать»много вещей и может быть принудительно освобожден одним?В этом случае вы могли бы рассмотреть возможность использования шаблона счетчика ссылок, больше похожего на старомодный COM.У этого, конечно, также есть проблемы, но они не являются проблемой в управляемом мире.

Проблема со счетчиком ссылок вокруг объекта заключается в том, что вы возвращаетесь к идее недействительного / неинициализированного объекта.Одним из возможных способов решения этой проблемы является предоставление счетчику ссылок действительного экземпляра «по умолчанию» (или фабричного делегата) для использования, когда все ссылки были освобождены, и кто-то все еще хочет экземпляр.

0 голосов
/ 12 января 2011

Хотя бывают случаи, когда событие Disposed (например, событие, используемое в Windows Forms) может быть полезным, события действительно добавляют немало накладных расходов. В случаях, когда объект будет хранить все IDisposables, которыми он когда-либо владеет, до тех пор, пока он не будет удален (обычная ситуация), может быть лучше сохранить List (Of IDisposable) и иметь закрытую функцию "T RegDisp (T obj), где T : IDisposable ", который добавит объект в список одноразовых и вернет его. Вместо установки поля для SomeDisposable, установите для него значение RegDisp (SomeDisposable). Обратите внимание, что в VB, если все вызовы конструктора заключены в фабричные методы, можно безопасно использовать RegDisp () в инициализаторах поля, но этого нельзя сделать в C #.

Кстати, если конструктор IDisposable принимает IDisposable в качестве параметра, часто может быть полезно, чтобы он принимал логическое значение, указывающее, будет ли передано право собственности на этот объект. Если возможно принадлежащий IDisposable будет представлен в изменяемом свойстве (например, PictureBox.Image), само свойство должно быть доступно только для чтения, с методом установки, который принимает флаг владения. Вызов метода set, когда объект владеет старым объектом, должен удалить старый объект перед установкой нового. Использование этого подхода устранит большую часть необходимости в событии Disposed.

...