2

我需要将参数(在 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;

给我一个错误,说代表不匹配(这是有道理的)

所以我的问题是:为什么当我传递参数时事件处理程序并没有真正分离,有没有办法绕过这个问题。

4

2 回答 2

6

当您创建一个 lambda(匿名)函数时,实际上每次都是在创建一个新函数。

你的前两行不起作用的原因是因为它们是两个完全不同的功能,只是碰巧做同样的事情。正确的分离方法是订阅和取消订阅一个函数,正如您已经知道的那样。

另一种可能不值得的方法是将您的 lambda 保存到一个变量中。

Action<object, MouseButtonEventArgs> myEventMethod = (sender, e) => _map_MouseLeftButtonUp2(sender, e, showResultsWindow);
_map.MouseLeftButtonUp += myEventMethod;
// ...
_map.MouseLeftButtonUp -= myEventMethod;
于 2013-08-01T13:29:49.927 回答
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 的地址以及您的两个代表不同

于 2013-08-01T13:33:55.903 回答