Unsubscribe anonymous method in C#

2018-12-31 08:17发布

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

If I subscribe to an event like this:

void MyMethod()
{
    Console.WriteLine("I did it!");
}

MyEvent += MyMethod;

I can un-subscribe like this:

MyEvent -= MyMethod;

But if I subscribe using an anonymous method:

MyEvent += delegate(){Console.WriteLine("I did it!");};

is it possible to unsubscribe this anonymous method? If so, how?

11条回答
时光乱了年华
2楼-- · 2018-12-31 08:39

One simple solution:

just pass the eventhandle variable as parameter to itself. Event if you have the case that you cannot access the original created variable because of multithreading, you can use this:

MyEventHandler foo = null;
foo = (s, ev, mehi) => MyMethod(s, ev, foo);
MyEvent += foo;

void MyMethod(object s, MyEventArgs ev, MyEventHandler myEventHandlerInstance)
{
    MyEvent -= myEventHandlerInstance;
    Console.WriteLine("I did it!");
}
查看更多
皆成旧梦
3楼-- · 2018-12-31 08:41

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.

查看更多
宁负流年不负卿
4楼-- · 2018-12-31 08:45

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);
        }
    }
}
查看更多
墨雨无痕
5楼-- · 2018-12-31 08:50

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.

查看更多
回忆,回不去的记忆
6楼-- · 2018-12-31 08:52
Action myDelegate = delegate(){Console.WriteLine("I did it!");};

MyEvent += myDelegate;


// .... later

MyEvent -= myDelegate;

Just keep a reference to the delegate around.

查看更多
登录 后发表回答