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

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

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

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

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

Ответы [ 3 ]

35 голосов
/ 30 апреля 2009

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

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

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

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

myObservableCollection.CollectionChanged += myDelegate;

myObservableCollection.CollectionChanged -= myDelegate;
20 голосов
/ 30 апреля 2009

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

1 голос
/ 17 ноября 2009

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

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

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

...