Unsubscribe anonymous method in C#

前端 未结 11 1237
夕颜
夕颜 2020-11-22 05:16

Is it possible to unsubscribe an anonymous method from an event?

If I subscribe to an event like this:

void MyMethod()
{
    Console.WriteLine(\"I di         


        
相关标签:
11条回答
  • 2020-11-22 05:49

    Instead of keeping a reference to any delegate you can instrument your class in order to give the event's invocation list back to the caller. Basically you can write something like this (assuming that MyEvent is declared inside MyClass):

    public class MyClass 
    {
      public event EventHandler MyEvent;
    
      public IEnumerable<EventHandler> GetMyEventHandlers()  
      {  
          return from d in MyEvent.GetInvocationList()  
                 select (EventHandler)d;  
      }  
    }
    

    So you can access the whole invocation list from outside MyClass and unsubscribe any handler you want. For instance:

    myClass.MyEvent -= myClass.GetMyEventHandlers().Last();
    

    I've written a full post about this tecnique here.

    0 讨论(0)
  • 2020-11-22 05:49

    If the best way is to keep a reference on the subscribed eventHandler, this can be achieved using a Dictionary.

    In this example, I have to use a anonymous method to include the mergeColumn parameter for a set of DataGridViews.

    Using the MergeColumn method with the enable parameter set to true enables the event while using it with false disables it.

    static Dictionary<DataGridView, PaintEventHandler> subscriptions = new Dictionary<DataGridView, PaintEventHandler>();
    
    public static void MergeColumns(this DataGridView dg, bool enable, params ColumnGroup[] mergedColumns) {
    
        if(enable) {
            subscriptions[dg] = (s, e) => Dg_Paint(s, e, mergedColumns);
            dg.Paint += subscriptions[dg];
        }
        else {
            if(subscriptions.ContainsKey(dg)) {
                dg.Paint -= subscriptions[dg];
                subscriptions.Remove(dg);
            }
        }
    }
    
    0 讨论(0)
  • 2020-11-22 05:51

    Since C# 7.0 local functions feature has been released, the approach suggested by J c becomes really neat.

    void foo(object s, MyEventArgs ev)
    {
        Console.WriteLine("I did it!");
        MyEvent -= foo;
    };
    MyEvent += foo;
    

    So, honestly, you do not have an anonymous function as a variable here. But I suppose the motivation to use it in your case can be applied to local functions.

    0 讨论(0)
  • 2020-11-22 05:57
    Action myDelegate = delegate(){Console.WriteLine("I did it!");};
    
    MyEvent += myDelegate;
    
    
    // .... later
    
    MyEvent -= myDelegate;
    

    Just keep a reference to the delegate around.

    0 讨论(0)
  • 2020-11-22 06:02

    From memory, the specification explicitly doesn't guarantee the behaviour either way when it comes to equivalence of delegates created with anonymous methods.

    If you need to unsubscribe, you should either use a "normal" method or retain the delegate somewhere else so you can unsubscribe with exactly the same delegate you used to subscribe.

    0 讨论(0)
  • 2020-11-22 06:02

    If you want to be able to control unsubscription then you need to go the route indicated in your accepted answer. However, if you are just concerned about clearing up references when your subscribing class goes out of scope, then there is another (slightly convoluted) solution which involves using weak references. I've just posted a question and answer on this topic.

    0 讨论(0)
提交回复
热议问题