附加带有传递参数的方法后分离事件处理程序

本文关键字:方法 分离 事件处理 程序 参数 | 更新日期: 2023-09-27 18:25:45

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

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

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

附加带有传递参数的方法后分离事件处理程序

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

前两行不起作用的原因是,它们是两个完全不同的函数,恰好做着相同的事情。正确的分离方式是订阅和取消订阅函数,正如您已经了解的那样。

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

Action<object, MouseButtonEventArgs> myEventMethod = (sender, e) => _map_MouseLeftButtonUp2(sender, e, showResultsWindow);
_map.MouseLeftButtonUp += myEventMethod;
// ...
_map.MouseLeftButtonUp -= myEventMethod;

原因是两个委托不相等:

  // 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.Equaals的工作方式与Object.ReferenceEquals的工作方式相同,后者检查实例引用(地址)。当然,x和y的地址以及两个您的代理人

是不同的