2009-07-21 91 views
0

也许一个愚蠢的问题,但..这是危险的吗?关于事件

在我的代码中,我在几个地方使用以下构造。

void MyFunction() 
{ 
    DoSomething(myClass.myProperty) 

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

所以我最初想做一些事情,并且在未来的财产变化时也这样做。

现在事情是,我的程序执行过程中MyFunction()会被调用几次。我将分配给PropertyChanged的委托添加到它通过此方法的加班吗? (每次迭代消耗更多内存并减慢程序速度)或者是编译器/运行时足够聪明以理解我应该只在第一次添加..?如果是这样,这是如何工作的?

+0

这对您来说可能不是问题,但是使用这种语法不可能从此事件中取消订阅匿名事件处理程序,这可能会导致一些内存问题。我建议编写函数,并将事件处理程序与+ = new eventhandler(function)相关联; – 2009-07-21 13:59:57

回答

3

许多其他的答案建议你应该检查PropertyChanged事件是否是null防止增加几个听众。该解决方案的一个问题是,如果代码的其他部分监听同一个事件,但是监听另一个属性,则此PropertyChanged可能不是null

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

更好的解决方案,在我看来,是保持一个布尔标志,它最初是假的,只有当MyFunction被称为设置为true。然后,检查这个标志是否需要添加事件处理程序。

4

编译器无法知道您的意图......它将忠实地附加每次调用MyFunction()的事件处理程序。

这样看 - 它们的编译器无法知道函数中的引用变量(例如myclass)是否指向您之前附加处理程序的对象的相同实例。它也不知道你在呼叫之间的其他地方没有分开处理程序。它不能做出这样的假设。

但是,您可以重构您的代码,以便该处理程序仅附加一次。由于其他消费者可能会订阅PropertyChanged事件,因此需要保留一些独立的状态以了解您是否已订阅或未订阅。例如:

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

谢谢。这里的一个问题也是myClass是一个单例,也可以从其他方法访问。所以其他人也可以添加他们的代表。我也需要为此找到一些东西。 – 2009-07-21 12:33:23

+0

检查null的解决方案对于PropertyChanged事件不可行,因为代码的其他部分可能使用相同的事件来侦听对不同属性的更改。看到我的答案不同的解决方案:http://stackoverflow.com/questions/1158849/is-this-dangerous-about-events/1158930#1158930 – 2009-07-21 12:40:20