我在StackOverflow上发现了关于事件和种族的这篇文章,这对我帮助很大 -
这里的关键声明是'即使在事件被取消订阅后,事件处理程序也必须是强大的,否则被调用'
我认为这意味着当您订阅某个活动时,即使您取消订阅该活动,您也必须为该活动做好准备,并进行某种检查以确定是否应该处理该活动。 / p>
这可能与
一样简单(丑陋)bool _acceptEvents;
// event handler
void LoggedIn(object sender, EventArgs a)
{
if (!_acceptEvents) return;
Evt("Now logged in");
}
// code to unsubscribe to event
_acceptEvents = false;
_parent.LoggedIn -= new LoggedInEventHandler(LoggedIn);
现在很明显,上面的代码看起来很糟糕,但它符合所需的目的。
我的问题是,这样做会更优雅吗?处理这种情况的典型方法是什么?
我想也许你可以做到
if (!_parent.LoggedIn.Contains(myhandler)) return;
但是我试过了,我想事件的设计是为了防止你看到其他订阅者。
您怎么看?
由于
答案 0 :(得分:1)
imho这是一个不存在的问题。您是否有过生成错误(或会产生错误)的代码,因为事件在取消订阅后被调用了?
答案 1 :(得分:0)
事实上,事件会封装多播委托的调用列表,因此您无法直接删除订阅。
取消注册后可以调用处理程序的主要原因(即使您可以从列表中删除订阅)是事件所有者可以制作调用列表的副本。
看看这段代码:
var ev = TheEvent;
if(ev != null)
{
ev(this, EventArgs.Empty);
}
第一行创建一个调用列表的副本,以防止在空列表的第4行引发事件(从而保护您免受空引用异常的影响)
因此,如果您在第1行和第4行之间取消注册,则仍会调用您的处理程序,因为已在ev
中复制了对它的引用。