C# - anonymous functions and event handlers

后端 未结 4 603
情深已故
情深已故 2021-02-02 10:50

I have the following code:

public List FindStepsByType(IWFResource res)  
{  
    List retval = new List&         


        
4条回答
  •  猫巷女王i
    2021-02-02 11:19

    Your code has a few problems (some you and others have identified):

    • The anonymous delegate cannot be removed from the event as coded.
    • The anonymous delegate will live longer than the life of the method calling it because you've added it to FoundStep which is a member of this.
    • Every entry into FindStepsByType adds another anonymous delegate to FoundStep.
    • The anonymous delegate is a closure and effectively extends the lifetime of retval, so even if you stop referencing retval elsewhere in your code, it's still held by the anonymous delegate.

    To fix this, and still use an anonymous delegate, assign it to a local variable, and then remove the handler inside a finally block (necessary in case the handler throws an exception):

      public List FindStepsByType(IWFResource res)
      {
         List retval = new List();
         EventHandler handler = (sender, e) =>
         {
            if (e.Step.ResourceType == res) retval.Add(e.Step);
         };
    
         this.FoundStep += handler;
    
         try
         {
            this.Start();
         }
         finally
         {
            this.FoundStep -= handler;
         }
    
         return retval;
      }
    

    With C# 7.0+ you can replace the anonymous delegate with a local function, achieving the same effect:

        public List FindStepsByType(IWFResource res)
        {
            var retval = new List();
    
            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;
        }
    

提交回复
热议问题