我需要将参数(在C#中)传递给事件处理程序,然后才能分离事件处理程序。
我附上事件处理程序并传递参数:
_map.MouseLeftButtonUp += (sender, e) => _map_MouseLeftButtonUp2(sender, e, showResultsWindow);
按预期调用事件。我尝试分离事件处理程序:
_map.MouseLeftButtonUp -= (sender, e) => _map_MouseLeftButtonUp2(sender, e, showResultsWindow);
代码执行时没有错误,但似乎没有分离。
如果我以更传统的方式附加事件处理程序(不传递参数):
_map.MouseLeftButtonUp+=_map_MouseLeftButtonUp;
和分离
_map.MouseLeftButtonUp -= _map_MouseLeftButtonUp;
一切都按预期工作
通过更传统的方式分离事件处理程序(带参数)
_map.MouseLeftButtonUp -= _map_MouseLeftButtonUp2;
给我一个错误,说代表不匹配(这是有道理的)
所以我的问题是:为什么在传递参数时事件处理程序并没有真正被分离,并且有办法解决这个问题。
答案 0 :(得分:5)
当你创建一个lambda(匿名)函数时,你实际上每次都在创建一个新函数。
你的前两行不起作用的原因是因为它们是两个完全不同的功能,它们碰巧做同样的事情。分离的正确方法是订阅和取消订阅函数,正如您已经想到的那样。
另一种可能不值得的方法是将lambda保存为变量。
Action<object, MouseButtonEventArgs> myEventMethod = (sender, e) => _map_MouseLeftButtonUp2(sender, e, showResultsWindow);
_map.MouseLeftButtonUp += myEventMethod;
// ...
_map.MouseLeftButtonUp -= myEventMethod;
答案 1 :(得分:1)
原因是两个代表不相等:
// You add one delegate instance
_map.MouseLeftButtonUp += (sender, e) => _map_MouseLeftButtonUp2(sender, e, showResultsWindow);
// ..And try to remove another one (not previous!) That's why the first delegate remains unremoved
_map.MouseLeftButtonUp += (sender, e) => _map_MouseLeftButtonUp2(sender, e, showResultsWindow);
您可以通过
说服自己 var x = (sender, e) => _map_MouseLeftButtonUp2(sender, e, showResultsWindow);
var y = (sender, e) => _map_MouseLeftButtonUp2(sender, e, showResultsWindow);
if (Object.Equals(x, y)) { // <- You expected this behaviour
...
}
else { // <- Alas, this is a real situation: x != y
...
}
这种行为的原因是当Object.Equals没有被覆盖时(并且在委托的情况下它不是)Object.Equals就像Object.RefrenceEquals那样,它检查实例引用(地址)。当然,x和y的地址以及两个代表
是不同的