C# - 匿名函数和事件处理程序
我有以下代码:
public List<IWFResourceInstance> FindStepsByType(IWFResource res)
{
List<IWFResourceInstance> retval = new List<IWFResourceInstance>();
this.FoundStep += delegate(object sender, WalkerStepEventArgs e)
{
if (e.Step.ResourceType == res) retval.Add(e.Step);
};
this.Start();
return retval;
}
请注意我如何将事件成员 (FoundStep) 注册到本地就地匿名函数。
我的问题是:当函数“FindStepByType”结束时 - 匿名函数是否会自动从事件的委托列表中删除,还是我必须在退出该函数之前手动删除它? (我该怎么做?)
我希望我的问题很清楚。
I have the following code:
public List<IWFResourceInstance> FindStepsByType(IWFResource res)
{
List<IWFResourceInstance> retval = new List<IWFResourceInstance>();
this.FoundStep += delegate(object sender, WalkerStepEventArgs e)
{
if (e.Step.ResourceType == res) retval.Add(e.Step);
};
this.Start();
return retval;
}
Notice how I register my event member (FoundStep) to local in-place anonymous function.
My question is: when the function 'FindStepByType' will end - will the anonymous function be removed automatically from the delegate list of the event or I have to manually remove it before steping out the function? (and how do I do that?)
I hope my question was clear.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
您的代码有一些问题(您和其他人已经发现了一些问题):
要解决此问题,并仍然使用匿名委托,请将其分配给局部变量,然后删除 finally 块内的处理程序(以防处理程序引发异常):
使用 C# 7.0+ 您可以用本地函数替换匿名委托,达到同样的效果:
Your code has a few problems (some you and others have identified):
To fix this, and still use an anonymous delegate, assign it to a local variable, and then remove the handler inside a finally block (necessary in case the handler throws an exception):
With C# 7.0+ you can replace the anonymous delegate with a local function, achieving the same effect:
以下是如何在匿名方法中取消订阅事件的方法:
Below is approach about how unsubscribe event in anonymous method:
不,它不会自动删除。从这个意义上说,匿名方法和“正常”方法之间没有区别。如果需要,您应该手动取消订阅该活动。
实际上,它也会捕获其他变量(例如示例中的
res
)并让它们保持活动状态(防止垃圾收集器收集它们)。No, it will not be removed automatically. In this sense, there's not a difference between an anonymous method and a "normal" method. If you want, you should manually unsubscribe from the event.
Actually, it'll capture other variables (e.g.
res
in your example) and keep them alive (prevents garbage collector from collecting them) too.当使用匿名委托(或 lambda 表达式)订阅事件时,您以后无法轻松取消订阅该事件。事件处理程序永远不会自动取消订阅。
如果你看一下你的代码,即使你在函数中声明并订阅了事件,但你订阅的事件是在类上的,所以一旦订阅,即使函数退出后,它也将始终被订阅。另一件需要意识到的重要事情是,每次调用此函数时,它将再次订阅该事件。这是完全合法的,因为事件本质上是多播委托并允许多个订阅者。 (这可能是也可能不是您想要的。)
为了在退出函数之前取消订阅委托,您需要将匿名委托存储在委托变量中并将委托添加到事件中。然后,您应该能够在函数退出之前从事件中删除委托。
由于这些原因,如果您稍后必须取消订阅该活动,则不建议使用匿名委托。请参阅如何:订阅和取消订阅事件(C# 编程指南) (特别是标题为“使用匿名方法订阅事件”的部分)。
When using an anonymous delegate (or a lambda expression) to subscribe to an event does not allow you to easily unsubscribe from that event later. An event handler is never automatically unsubscribed.
If you look at your code, even though you declare and subscribe to the event in a function, the event you are subscribing to is on the class, so once subscribed it will always be subscribed even after the function exits. The other important thing to realize is that each time this function is called, it will subscribe to the event again. This is perfectly legal since events are essentially multicast delegates and allow multiple subscribers. (This may or may not be what you intend.)
In order to unsubscribe from the delegate before you exit the function, you would need to store the anonymous delegate in a delegate variable and add the delegate to the event. You should then be able to remove the delegate from the event before the function exits.
For these reasons, if you will have to unsubscribe from the event at some later point it is not recommended to use anonymous delegates. See How to: Subscribe to and Unsubscribe from Events (C# Programming Guide) (specifically the section titled "To subscribe to events by using an anonymous method").