2009-04-30 7 views
26

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

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

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

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

+0

? Дубликат: http://stackoverflow.com/questions/183367/unsubscribe-anonymous-method-in-c – Richard

+0

См. [Это] (http://stackoverflow.com/questions/183367/unsubscribe-anonymous-method -в-с). –

+0

Я не помещал свое лямбда-выражение в делегат (как в вашей ссылке), поэтому у меня нет ссылки на отмену подписки. –

ответ

20

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

+2

Если «конкретный синтаксис» означает создание лямбды и добавление обработчика в одну строку, тогда да. Простое решение просто хранит ссылку на лямбда. Действительно, я думаю, что OP должен смотреть на использование обычного метода, если ему нужно ссылаться на него неоднократно - это улучшает читаемость, по крайней мере, на мой взгляд. – Noldorin

+0

Спасибо, что поняли это. –

+0

@Noldorin Да, вот что я имел в виду под «этим конкретным синтаксисом». И я полностью согласен с тобой. –

35

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

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

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

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

myObservableCollection.CollectionChanged += myDelegate; 

myObservableCollection.CollectionChanged -= myDelegate; 
+0

var myDelegate = delegate (отправитель, e) {UpdateMyUI()}; не компилируется ... вам нужно указать тип делегата. Джон Скит использует делегат Action в своем примере, но он принимает только один аргумент. Какой тип делегата мы должны использовать в вашем примере? –

+1

@RaduSimionescu: То же, что и тип события, который в этом примере будет «NotifyCollectionChangedEventHandler» –

1

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

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

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

Смежные вопросы