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

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

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

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

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

Ответ 1

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

Ответ 2

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

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

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

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

myObservableCollection.CollectionChanged += myDelegate;

myObservableCollection.CollectionChanged -= myDelegate;

Ответ 3

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

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

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