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:26

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.

查看更多
倾城一夜雪
3楼-- · 2018-12-31 08:26

Kind of lame approach:

public class SomeClass
{
  private readonly IList<Action> _eventList = new List<Action>();

  ...

  public event Action OnDoSomething
  {
    add {
      _eventList.Add(value);
    }
    remove {
      _eventList.Remove(value);
    }
  }
}
  1. Override the event add/remove methods.
  2. Keep a list of those event handlers.
  3. When needed, clear them all and re-add the others.

This may not work or be the most efficient method, but should get the job done.

查看更多
ら面具成の殇う
4楼-- · 2018-12-31 08:27

One technique is to declare a variable to hold the anonymous method which would then be available inside the anonymous method itself. This worked for me because the desired behavior was to unsubscribe after the event was handled.

Example:

MyEventHandler foo = null;
foo = delegate(object s, MyEventArgs ev)
    {
        Console.WriteLine("I did it!");
        MyEvent -= foo;
    };
MyEvent += foo;
查看更多
余生请多指教
5楼-- · 2018-12-31 08:29

In 3.0 can be shortened to:

MyHandler myDelegate = ()=>Console.WriteLine("I did it!");
MyEvent += myDelegate;
...
MyEvent -= myDelegate;
查看更多
姐姐魅力值爆表
6楼-- · 2018-12-31 08:29

if you want refer to some object with this delegate, may be you can use Delegate.CreateDelegate(Type, Object target, MethodInfo methodInfo) .net consider the delegate equals by target and methodInfo

查看更多
余生无你
7楼-- · 2018-12-31 08:35

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.

查看更多
登录 后发表回答