#c# #event-handling
#c# #обработка событий
Вопрос:
У меня есть класс:
public abstract class BaseComponent { ... }
Внутри конструктора этого класса мы подписываемся на обработчик событий, например
protected ObjectWithEventHandler eventObject { get; private set; }
public BaseComponent (ObjectWithEventHandler obj)
{
eventObject = obj;
eventObject.ChangedEvent = new EventHandler(eventObject_OnChangedEvent );
}
protected void eventObject_OnChangedEvent (object sender, EventArgs e) { ... }
Существуют ли какие-либо жесткие и быстрые правила, когда дело доходит до подписки и отмены подписки на EventHandler?
Считается ли хорошей практикой предоставлять некоторый код очистки, который отменяет подписку на функцию от обработчика событий? Т.е. Реализовать IDisposable и затем отказаться от подписки от обработчика событий?
Или я излишне беспокоюсь?
Комментарии:
1. Я почти уверен, что вам не нужно беспокоиться об этом. C # должен очищать любые ссылки на события, когда ваш экземпляр получает сбор мусора (т. Е. Больше Не находится в области видимости или На экземпляр больше нигде не ссылаются)
2. @musefan, история немного сложнее: вам нужно учитывать время жизни задействованных объектов.
Ответ №1:
Если у вас есть полный контроль над использованием BaseComponent и вы знаете, что жизненный цикл EventObject короче или равен * в отношении жизненного цикла BaseComponent , вы можете пропустить код отмены подписки.
Во всех остальных случаях я бы включил его. В этом случае реализация IDisposable является хорошим стилем.
*) по сути, вы связываете время жизни EventObject с BaseComponent, поэтому оно не может быть короче, но оно все равно может быть равным, когда оба выходят за рамки вместе.
Ответ №2:
Пока объект, который предоставляет event ( eventObject
), создается внутри BaseComponent
класса, вы можете игнорировать явную отмену подписки, потому что она будет GCed автоматически, но явная отмена подписки в любом случае является хорошей практикой.
Но если вы подписываетесь на событие, которое передается внешним объектом, введенным в BaseComponent
вас, вы должны реализовать IDisposable в BaseComponent
классе и в Dispose()
методе do cleanup.
Ответ №3:
Вы должны предоставить какой-либо способ явно инициировать отмену подписки, если есть вероятность, что EventObject может жить дольше, поскольку предполагается, что экземпляры классов, производных от BaseComponent, будут жить. В противном случае вы бы предотвратили сборку мусора вашего компонента, поскольку EventObject содержит ссылку на него.
Реализация IDisposable() — хороший способ добиться этого, если вы можете быть уверены, что на самом деле существует какой-то код, вызывающий его. Завершитель не будет вызывать Dispose() , потому что сборщик мусора не будет пытаться очистить ваш компонент, пока он подписан на EventObject .ChangedEvent и EventObject все еще работают.