EventHandlers и анонимные делегаты / лямбда-выражения - PullRequest
11 голосов
/ 13 января 2009

Я надеюсь кое-что прояснить с помощью анонимных делегатов и лямбда-выражений, используемых для создания метода для обработчиков событий в C #, по крайней мере для меня.

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

SomeClass.SomeEvent += delegate(object o, EventArg e) { /* do something */ };

Я читал, что люди в прошлом забыли о событиях, у которых все еще есть обработчики, которые не позволяют классу собирать мусор. Как можно было бы удалить добавленный обработчик, не устанавливая для SomeEvent значение null в классе. Разве следующее не будет совершенно новым обработчиком?

SomeClass.SomeEvent -= delegate(object o, EventArg e) { /* do something */ };

Я видел хранение анонимного делегата или лямбда-выражения в переменной. Но это, по крайней мере, мне кажется, сводит на нет всю цель возможности просто и кратко добавить обработчик событий.

SomeEventDelegate handler = new SomeEventDelegate(delegate(object o, EventArg e) { /* do something */ });
SomeClass.SomeEvent += handler;
// ... stuff
SomeClass.SomeEvent -= handler;

Опять же, я понимаю, что вы могли бы просто сделать ...

public override Dispose(bool disposing)
{
    _someEvent = null;
    this.Dispose();
}

Но мне интереснее просто удалить динамически созданный метод из события. Надеюсь, кто-то может пролить свет на это для меня. Спасибо!

Ответы [ 3 ]

10 голосов
/ 13 января 2009

Если у объекта X есть обработчик событий, у которого target - это объект Y, то объект X, будучи живым, означает, что объект Y не может быть подвергнут сборке мусора. Это не останавливает сборку мусора для объекта X.

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

Проблема с событиями и GC заключается в том, что если вы забудете удалить подписанный обработчик из другого объекта - то есть у вас есть прослушиватель, который удаляется, но никогда не будет собирать мусор, потому что есть ссылка это из события в другом объекте.

1 голос
/ 13 января 2009

Думаю, проблема в том, что вы, похоже, исходите из предположения, что наличие делегата, назначенного событию объекта, предотвращает его GCed.

Это простое утверждение не соответствует действительности.

При этом сказанное исчезает.

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

Как такой графический процесс может достичь этого объекта?

0 голосов
/ 13 января 2009

Вы не можете.

Так же, как вы не можете создать анонимный тип вне его области видимости (за исключением некоторых трюков с компилятором).

Вот почему он называется анонимным.

Вы должны сохранить ссылку где-нибудь ... или использовать отражение.

...