是否可以从事件中取消订阅匿名方法?

如果我订阅了这样的活动:

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

MyEvent += MyMethod;

我可以像这样取消订阅:

MyEvent -= MyMethod;

但如果我使用匿名方式订阅:

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

是否可以取消订阅此匿名方法?如果有,怎么做?


当前回答

一种技术是声明一个变量来保存匿名方法,该变量将在匿名方法本身内部可用。这对我来说很有效,因为我想要的行为是在事件处理后取消订阅。

例子:

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

其他回答

如果你想用这个委托引用一些对象,你可以使用委托。创建elegate(类型,对象目标,MethodInfo MethodInfo) .net考虑委托equals by target和methodInfo

从记忆中来看,当涉及到用匿名方法创建的委托的等价性时,规范明确地没有保证行为的任何一种方式。

如果您需要退订,您应该使用“正常”方法或将委托保留在其他地方,这样您就可以使用与订阅时完全相同的委托退订。

一个简单的解决办法:

只需将eventandle变量作为参数传递给自身。 事件,如果你的情况下,你不能访问原始创建的变量,因为多线程,你可以使用这个:

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.0中可以缩短为:

MyHandler myDelegate = ()=>Console.WriteLine("I did it!");
MyEvent += myDelegate;
...
MyEvent -= myDelegate;

如果您希望能够控制取消订阅,那么您需要按照您接受的答案中指示的路线进行。但是,如果您只关心在订阅类超出作用域时清除引用,那么还有另一种解决方案(有点复杂),它涉及使用弱引用。我刚刚就这个话题发布了一个问答。