Как отписаться от события, которое использует лямбда-выражение?

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

myObservableCollection.CollectionChanged += ((sender, e) => UpdateMyUI());

Прежде всего, это хороший способ сделать это?

Второе: какой код отписаться от этого события? Это то же самое, но с -= (а затем снова полный анонимный метод)?

3 ответа

Решение

Если вам нужно отписаться от события, вам нужна ссылка на экземпляр. К сожалению, это означает, что вы не можете использовать этот конкретный синтаксис.

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

Я полагаю, что ранее Джон Скит указывал, что "спецификация явно не гарантирует поведения в любом случае, когда речь идет об эквивалентности делегатов, созданных анонимными методами".

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

var myDelegate = delegate(sender, e){UpdateMyUI()};

myObservableCollection.CollectionChanged += myDelegate;

myObservableCollection.CollectionChanged -= myDelegate;

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

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

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

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