Когда анонимные делегаты удаляются из событий? - PullRequest
1 голос
/ 25 февраля 2011

Если я напишу что-то вроде

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

И вывод, когда я нажимаю «Ввод» несколько раз, равен

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 ]

1 голос
/ 25 февраля 2011

Нет (простого) способа удалить делегатов, которые вы сначала не присвоили какой-либо переменной.Неважно, анонимны они или нет.Вы можете назначить анонимный делегат переменной и удалить его позже:

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

Аналогичным образом, нет простого способа удалить делегат, если вы зарегистрируете его с помощью:

form.Click += new EventHandler(foo);

.проблема с событиями заключается в том, что они собираются только тогда, когда объект, к которому они присоединены, является сборщиком мусора (даже если на целевой объект, с которым они работают, нет ссылки из какой-либо другой части программы, и поэтому они не могут выполнять какую-либо полезную работу),

Это можно решить с помощью слабых событий .Вместо того, чтобы удалять их явно, вы используете некоторые механизмы, которые позволяют GC иметь дело с ними автоматически.

1 голос
/ 25 февраля 2011

Он никогда не будет автоматически удален из события.

Если вы хотите отписаться от анонимного делегата, проверьте этот вопрос:

Отписаться от анонимного метода в C #

...