何时从事件中删除匿名代表?

时间:2011-02-25 01:58:57

标签: c# delegates anonymous-delegates

如果我写的话

myDataModel.ContentLoaded += (o,e) => { DoSomething(); }

当(如果有的话)匿名委托从事件中移除时?

作为一个简单的例子,我可以编写这个程序

class Program
{
    public event EventHandler<EventArgs> MyEvent = delegate { };

    static void Main(string[] args)
    {
        Program p = new Program();
        while(true)
        {
            p.MyEvent += (o, e) => Console.WriteLine("Hello!");

            Console.ReadLine();
            p.Foo();
        }
    }

    void Foo()
    {
        MyEvent(this, EventArgs.Empty);
    }
}

我反复按'Enter'输出

Hello!

Hello!
Hello!

Hello!
Hello!
Hello!

Hello!
Hello!
Hello!
Hello!

......等等。我可以添加一行

p.MyEvent -= (o, e) => Console.WriteLine("Hello!");

p.Foo()之后但当然没有效果,因为我正在删除一个完全不同的匿名代表。

那么这个问题是什么?有什么方法可以删除这些匿名代表吗?例如,对于使用

等表达式提取数据的异步Silverlight应用程序有什么影响
_myDataContext.Load(myQuery, loadOperation =>
    {
        // do stuff with the data here
    }, null);

?我假设这些类型的回调没有使用事件来实现,但当然不可能(?)告诉。

如果不仔细考虑,匿名代表是否危险?

2 个答案:

答案 0 :(得分:1)

永远不会自动从活动中删除。

如果您想取消订阅匿名代表,请查看以下问题:

Unsubscribe anonymous method in C#

答案 1 :(得分:1)

没有(简单)方法可以删除您没有首先为任何变量提供帮助的代理。它们是否是匿名的并不重要。您可以将匿名委托分配给变量并在以后删除它:

EventHandler eh = (src, e) => Console.WriteLine("Hello");
form.Click += eh; 
// At some later point
form.Click -= eh;

同样,如果您使用以下命令删除委托,则没有(简单)方法删除委托:

form.Click += new EventHandler(foo);

事件的问题是它们只是在它们所附加的对象被垃圾收集时被垃圾收集(即使它们使用的目标对象没有从程序的任何其他部分引用,因此它们不能任何有用的工作)。

这可以使用weak events来解决。您可以使用一些允许GC自动处理它们的机制,而不是显式删除它们。