我最近被问了一个问题,如果我查询一个处理程序两次会发生什么。让我给你看看代码:为一个事件查询一个代表两次
public delegate void OpenEventHandler(object sender, EventArgs e);
public class MyWindow
{
public event OpenEventHandler Open;
public void OpenWindow()
{
if (Open != null)
{
Open(this, new EventArgs());
}
}
}
public class TwoDelegates
{
public static void HandleOpen(Object sender, EventArgs e)
{
Console.WriteLine("Birds fly");
(sender as MyWindow).Open -= HandleOpen;
}
public static void Run()
{
var window = new MyWindow();
window.Open += HandleOpen;
window.Open += HandleOpen;
window.OpenWindow();
Console.ReadKey();
}
}
我想知道为什么字符串仍然打印两次。在它的开头部分,“调用”列表由两个具有相同代表引用的项目组成,但在第一次运行后它将被清理,仍然会出现调用请求。
UPDATE1:
似乎连简单-=
只删除一个条目:在VS2010
var window = new MyWindow();
window.Open += HandleOpen;
window.Open += HandleOpen;
Console.WriteLine(window.getHandlers().Count());
window.Open -= HandleOpen;
Console.WriteLine(window.getHandlers().Count());
虽然调试模式,而你通过window.Open
内部属性显示了0计数空的调用列表。看起来这在VS中显示的调试信息中有些神奇。
你能解释一下它有点详细吗?我基本上试图通过发送访问发件人对象来清理原始事件的invocaiton列表。首先' - ='真正清理'sender'的窗口对象'Open.NonPublic.InvocationsList'属性的调用列表,它甚至在调试窗口中显示。但'GetInvocationList()'仍然返回一个处理程序。 – 2013-04-25 08:50:42
@Johnny_D这个答案的重点在于那并不重要。清除调用列表只会影响将来调用事件时运行哪些处理程序。更改在当前调用事件时将运行哪些处理程序为时已晚,因为调用列表在调用时会被复制。 – Servy 2013-04-25 13:52:55
好的,很明显。但我仍然想知道现场发生了什么,为什么VS2010的行为显示空的调用列表,尽管GetInvocationList返回一个条目。 – 2013-04-25 14:09:40