2009-07-21 6 views
0

Возможно, глупый вопрос, но ...Это опасно? О событиях

В моем коде я использую следующую конструкцию в нескольких местах.

void MyFunction() 
{ 
    DoSomething(myClass.myProperty) 

    myClass.PropertyChanged += (s,e) => { 
     if (e.PropertyName == "myProperty") { 
     DoSomething(myClass.myProperty); 
     } 
    } 
} 

Поэтому я хочу что-то сделать изначально, а также сделать то же самое, когда свойство изменится в будущем.

Теперь дело в том, что MyFunction() вызывается несколько раз во время выполнения моей программы. Будет ли добавлен делегат, который я присваиваю PropertyChanged, через evertime, который проходит через этот метод? (потребляя больше памяти на каждой итерации и замедляя работу программы) Или компилятор/среда выполнения достаточно умны, чтобы понять, что я должен быть добавлен только в первый раз ..? И если да, то как это работает?

+0

Это не проблема для вас, но с этим синтаксисом невозможно отменить анонимный обработчик событий из этого события, что может привести к некоторым проблемам с памятью. Я бы рекомендовал написать функцию и просто прикрепить обработчик событий с помощью + = new eventhandler (function); –

ответ

3

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

void AnotherFunction() 
{ 
    myClass.PropertyChanged += (s,e) => { 
    if (e.PropertyName == "anotherProperty") { 
     DoSomethingElse(myClass.anotherProperty); 
    } 
    } 
} 

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

+0

Спасибо, самый полный ответ –

4

Компилятор не может знать ваши намерения ... он будет верно прикреплять обработчик событий при каждом вызове функции MyFunction().

Посмотрите на это так: компилятор не может знать, что ссылочные переменные (например, myclass) в вашей функции относятся к тем же экземплярам объектов, к которым вы прикрепляли обработчики ранее. Он также не может знать, что вы не отделили обработчик где-то еще между вызовами. Он не может делать такие предположения.

Вы, однако, можете перестроить свой код, чтобы обработчик был присоединен только один раз. Поскольку другие пользователи могут подписаться на событие PropertyChanged, вам нужно сохранить какое-то независимое государство, чтобы узнать, подписаны ли вы или нет. Например:

if(!haveSubscribedToPropertyChanged) { 
    myClass.PropertyChanged += (s,e) => { 
      if (e.PropertyName == "myProperty") { 
       DoSomething(myClass.myProperty); 
      } 
     } 
     haveSubscribedToPropertyChanged = true; 
     } 
+0

Спасибо. Проблема здесь также в том, что myClass - это синглтон, к которому также можно получить доступ из других методов. Поэтому другие могут добавить делегатов. Мне нужно найти что-то для этого тоже. –

+0

Решение проверки на null не является жизнеспособным для события PropertyChanged, так как другие части кода могут использовать одно и то же событие для прослушивания изменений в разных свойствах. См. Мой ответ для другого решения: http://stackoverflow.com/questions/1158849/is-this-dangerous-about-events/1158930#1158930 –

+0

Хорошая точка. Я пересмотрю свой ответ. – LBushkin

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