Обработчики событий и анонимные делегаты / лямбда-выражения

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

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

Я имел в виду точно такой же вопрос, и вам удалось его очень ясно выразить.

Stefano Ricciardi 13.05.2011 13:18
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
11
1
6 084
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

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

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

С учетом сказанного мнимая проблема исчезает.

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

Как такой процесс построения графиков смог бы прийти к этому объекту?

Утверждение верно, поскольку обработчик событий добавляется во внутренне управляемый список обработчиков.

Kent Boogaart 13.01.2009 18:02

Если вы не будете осторожны, затвор может укусить вас под задницу.

user1228 13.01.2009 18:05

@Will: Вам действительно нужно объясниться. Может быть, с вашим собственным ответом и примером того, как закрытие может так укусить?

AnthonyWJones 13.01.2009 18:27

@Kent: У вас есть ссылка на этот список обработчиков, управляемый изнутри?

AnthonyWJones 13.01.2009 18:31

Поищите здесь кусочек задницы: stackoverflow.com/questions/371109/…

Benjol 16.06.2009 15:01
Ответ принят как подходящий

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

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

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

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

user1228 13.01.2009 18:02

Интересный факт: когда ToolStrip становится видимым, он регистрируется в System.UserPreferenceChanged. Поэтому, если вы удалите ToolStrip из его контейнера, не установив для параметра Visible значение false, он никогда не будет удален. Вот почему рано или поздно вам понадобится профилировщик памяти.

Robert Rossney 13.01.2009 21:19

Вы не можете.

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

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

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

Я полагаю, что то же самое и с анонимными объектами. SomeClass.SomeEvent + = новый SomeEventHandler (SomeMethod); нельзя было бы удалить, не установив для события значение null, не так ли?

Nicholas Mancuso 13.01.2009 19:47

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