首页 > 解决方案 > 取消订阅委托与函数中的事件

问题描述

为什么当事件处理程序定义为函数时 C# 允许取消订阅事件,但当事件处理程序定义为委托时不允许?

考虑以下有效的代码:

void SomeFunction()
{
  var eventRaiser = ClassRaisingEvent.GetEventRaiser();

  void handler(object sender, EventArgs ev)
  {
    ProcessData(ev);
    eventRaiser.OnEvent -= handler;
  }

  eventRaiser.OnEvent += handler
  eventRaiser.Process();
}

但这无法在指定的位置编译:

void SomeFunction()
{
  var eventRaiser = ClassRaisingEvent.GetEventRaiser();

  DelegateType handler = (object sender, EventArgs ev) =>
  {
    ProcessData(ev);
    eventRaiser.OnEvent -= handler; // FAILS here with "Use of unassigned local variable 'handler '"
  }

  eventRaiser.OnEvent += handler
  eventRaiser.Process();
}

编辑:这个问题不是如何退订。这就是为什么(在技术意义上)函数名称被捕获在函数的范围内,但委托的不是。

EDIT2:在此处回答 (尤其是答案中的第 2 点)解释了我所看到的行为。

标签: c#eventsdelegates

解决方案


本地函数是在编译时定义的,就像其他函数一样。handler但是,该变量仅在运行时才知道。因此,正如编译器告诉您的那样,您不能在handler变量被赋值之前使用该变量,这意味着在}您的委托关闭之后。

要使第二个代码段正常工作,您可以做的是首先初始化变量:

void SomeFunction()
{
  var eventRaiser = ClassRaisingEvent.GetEventRaiser();

  DelegateType handler = null;
  handler = (object sender, EventArgs ev) =>
  {
    ProcessData(ev);
    eventRaiser.OnEvent -= handler;
  };

  eventRaiser.OnEvent += handler;
  eventRaiser.Process();
}

推荐阅读