WeakReference и обработка событий

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

В качестве аргумента для этого:

Люди говорят, что если вы подписываетесь на что-то свое, ваша ответственность за отмену подписки и вы должны это сделать.

Ответ 1

Хорошо, когда вы можете привыкнуть отказаться от подписки на события, но иногда нет очевидного метода "очистки", где это можно сделать. Недавно мы опубликовали статью статьи в блоге по этому вопросу; он включает методы, облегчающие подписку на событие с помощью WeakReference.

Ответ 2

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

Ответ 3

Слабые ссылки сами по себе не решают проблему, поскольку делегат держит ссылку. В составной библиотеке приложений, которая поставляется с Prism (www.microsoft.com/compositewpf), есть класс WeakDelegate, который вы можете извлечь из источника. The WeakDelegate в основном отражает и создает делегата только на мгновение, а затем освобождает его, тем самым не имея никаких указателей. В пределах CAL он используется классом EventAggregator, но вы можете разрывать его для собственного использования, так как он находится под MS-PL.

Ответ 4

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

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