Подтвердить что ты не робот

Должен ли я всегда отключать обработчики событий в методе Dispose?

Я работаю на С#, и мое рабочее место имеет некоторые стандарты кода. Один из них заключается в том, что каждый обработчик событий, который мы связываем (например, KeyDown), должен быть отключен в методе Dispose. Есть ли веская причина для этого?

4b9b3361

Ответ 1

Если вы не ожидаете, что издатель события переживет абонента, нет причин удалить обработчик событий, нет.

Это одна из тех тем, где народные знания выросли. Вам просто нужно думать об этом в обычном режиме: издатель (например, кнопка) имеет ссылку на подписчика. Если и издатель, и подписчик будут иметь право на сбор мусора в одно и то же время (как это обычно бывает), или если издатель будет иметь право на сбор мусора раньше, тогда нет проблемы с GC.

Статические события вызывают проблему с GC, потому что они фактически являются издателем бесконечно долгоживущих - я, возможно, препятствовал статическим событиям. (Я очень редко нахожу их полезными.)

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

Ответ 2

У меня была большая утечка GDI в моем приложении, если я не отменил регистрацию обработчиков событий в Dispose() пользовательского элемента управления, который динамически создавался и уничтожался. Я нашел следующее в справке Visual Studio 2013 в Руководстве по программированию на С#. Обратите внимание на то, что я выделил курсивом:

Как сделать: Подписываться и отменить подписку на события.

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

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