Как отменить регистрацию анонимного обработчика событий
Скажи, если я слушаю событие:
Subject.NewEvent += delegate(object sender, NewEventArgs e)
{
//some code
});
Теперь, как мне отменить регистрацию этого события? Или просто позволить памяти просочиться?
7 ответов
Если вам нужно отменить регистрацию события, я рекомендую избегать анонимных делегатов для обработчика событий.
Это один из случаев, когда лучше назначить это локальному методу - вы можете просто отписаться от события.
Дайте вашему экземпляру анонимного делегата имя:
EventHandler<NewEventArg> handler = delegate(object sender, NewEventArgs e)
{
//some code
};
Subject.NewEvent += handler;
Subject.NewEvent -= handler;
Чтобы удалить обработчик при первом вызове:
//SubjectType Subject = ..... already defined if using (2)
EventHandler handler = null;
handler = delegate(object sender, EventArgs e)
{
// (1)
(sender as SubjectType).NewEvent -= handler;
// or
// (2) Subject.NewEvent -= handler;
// do stuff here
};
Subject.NewEvent += handler;
Вы можете создать метод для отмены регистрации от всех слушателей события. Это не совсем то, что вы хотите, но иногда это может быть полезно. Например (это действительно работает =)):
class Program {
static void Main(string[] args) {
A someClass = new A();
someClass.SomeEvent += delegate(object sender, EventArgs e) {
throw new NotImplementedException();
};
someClass.ClearEventHandlers();
someClass.FireEvent();
Console.WriteLine("No error.");
}
public class A {
public event EventHandler SomeEvent;
public void ClearEventHandlers() {
Delegate[] delegates = SomeEvent.GetInvocationList();
foreach (Delegate delegate in delegates) {
SomeEvent -= (EventHandler) delegate;
}
}
public void FireEvent() {
if (SomeEvent != null) {
SomeEvent(null, null);
}
}
}
}
Вам нужно имя для вашей анонимной функции, а затем вы можете сделать это только в том случае, если имя находится в области видимости:
var handler = new EventHandler(delegate(object o, EventArgs e)
{
//do something...
};
Subject.NewEvent += handler;
// later on while handler is still in scope...
Subject.NewEvent -= handler;
Есть еще один (мой) вопрос, который затрагивает это в некоторых (слишком много) деталях: слабая модель обработчика событий для использования с лямбдами.
Однако теперь, когда появилась Reactive Framework, я бы серьезно подумал об этом в такой ситуации.
Вам нужно отменить регистрацию по какой-либо причине, кроме утечки?
Что касается бита "Или просто позволить утечке памяти", то, когда Subject очищается сборщиком мусора, ваш анонимный делегат также должен быть очищен, чтобы не было утечки.