1

如果我写类似

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);

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

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

4

2 回答 2

1

它永远不会自动从事件中删除。

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

在 C# 中取消订阅匿名方法

于 2011-02-25T02:04:42.973 回答
1

没有(简单的)方法可以删除您没有首先分配给任何变量的委托。他们是否匿名并不重要。您可以将匿名委托分配给变量并稍后将其删除:

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

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

form.Click += new EventHandler(foo);

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

这可以使用弱事件来解决。您无需显式删除它们,而是使用一些允许 GC 自动处理它们的机制。

于 2011-02-25T02:05:26.590 回答