C# - 匿名函数和事件处理程序

标签 c# scope anonymous-methods

我有以下代码:

public List<IWFResourceInstance> FindStepsByType(IWFResource res)  
{  
    List<IWFResourceInstance> retval = new List<IWFResourceInstance>();  
    this.FoundStep += delegate(object sender, WalkerStepEventArgs e)   
                      {   
                        if (e.Step.ResourceType == res) retval.Add(e.Step);   
                      };  
    this.Start();  
    return retval;
}  

请注意我是如何将我的事件成员 (FoundStep) 注册到本地就地匿名函数的。

我的问题是:“FindStepByType”函数何时结束——匿名函数会自动从事件的委托(delegate)列表中删除,还是我必须在退出该函数之前手动删除它? (我该怎么做?)

我希望我的问题很清楚。

最佳答案

您的代码有一些问题(您和其他人已经确定了一些问题):

  • 无法按照编码从事件中删除匿名委托(delegate)。
  • 匿名委托(delegate)的生命周期将比调用它的方法的生命周期长,因为您已将它添加到this 的成员FoundStep
  • 每次进入 FindStepsByType 都会向 FoundStep 添加另一个匿名委托(delegate)。
  • 匿名委托(delegate)是一个闭包,有效地延长了 retval 的生命周期,因此即使您停止在代码的其他地方引用 retval,它仍然由匿名委托(delegate)持有.

要解决这个问题,并且仍然使用匿名委托(delegate),将其分配给一个局部变量,然后删除 finally block 中的处理程序(在处理程序抛出异常的情况下是必需的):

  public List<IWFResourceInstance> FindStepsByType(IWFResource res)
  {
     List<IWFResourceInstance> retval = new List<IWFResourceInstance>();
     EventHandler<WalkerStepEventArgs> handler = (sender, e) =>
     {
        if (e.Step.ResourceType == res) retval.Add(e.Step);
     };

     this.FoundStep += handler;

     try
     {
        this.Start();
     }
     finally
     {
        this.FoundStep -= handler;
     }

     return retval;
  }

在 C# 7.0+ 中,您可以将匿名委托(delegate)替换为本地函数,从而达到相同的效果:

    public List<IWFResourceInstance> FindStepsByType(IWFResource res)
    {
        var retval = new List<IWFResourceInstance>();

        void Handler(object sender, WalkerStepEventArgs e)
        {
            if (e.Step.ResourceType == res) retval.Add(e.Step);
        }

        FoundStep += Handler;

        try
        {
            this.Start();
        }
        finally
        {
            FoundStep -= Handler;
        }

        return retval;
    }

关于C# - 匿名函数和事件处理程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1389543/

相关文章:

arrays - 在 Julia 的函数中重新分配字典值

javascript - javascript 中嵌套匿名方法的闭包

c# - NopCommerce 3.1 中的数据访问插件

c# - 在Prime31中传递给函数时,在unity3d项目的ios中引发错误

c# - 保存到现有文本文件的末尾 c#

c# - 将匿名方法分配给委托(delegate)时,协变和逆变不起作用

c# - C# 在 foreach 中重用变量是否有原因?

c# - 使用 Foreach 子句的 Lambda 表达式

c++ - 跟踪自动变量的生命周期?

Javascript:对象中的范围问题