Вопрос

Я надеюсь кое-что прояснить с помощью анонимных делегатов и лямбда-выражений, используемых для создания метода для обработчиков событий в 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();
}

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

Это было полезно?

Решение

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

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

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

Другие советы

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

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

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

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

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

Вы не можете.

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top